Avoiding axis tick label collision in faceted ggplots

依然范特西╮ 提交于 2019-12-03 05:59:47

EDIT Updated to ggplot2 ver 3.0.0

One possibility might be to modify the build data. It is possible to take the limits of the original plot, and apply a multiplicative expansion factor. The relative positions of the major and minor breaks also need adjustment. Note that the function allows selection of the panels to which the expansion is to apply.

What's the difference between this and using expand within scale_y_continuous (apart from being able to select the panels)? This function leaves the breaks (and the tick marks and grid lines) as they were in the original. It's just that they take up less space. expand, however, will compress the scale but ggplot will add new labels, grid lines and tick marks if it can.

It would not take much to break the function - ggplot has been known to change the names of the elements of the build data in recent versions.

dd <- data.frame(x=rep(1:3,3),
                 y=c(0.1,0.2,0.3,
                     0.1,0.4,0.6,
                     1,2,3),
                 f=factor(rep(letters[1:3],each=3)))
library(ggplot2)


p = ggplot(dd,aes(x,y))+
   facet_grid(f~.,scale="free")+
   geom_point()+
   theme_bw(base_size=24)+
   theme(panel.spacing=grid::unit(0,"lines"))


expand = function(plot, mult = 0.1, applyTo) {
# Get the build data
gd = ggplot_build(plot)

# Get the original limits,
# and calculate the new limits,
# expanded according to the multiplicative factor
limits <- sapply(gd$layout$panel_params, "[[", "y.range")    # Original limits
fac = mult*(limits[2,] - limits[1, ])  
newlimits = rbind(limits[1, ] - fac, limits[2, ] + fac)

# The range for the new limits
range = newlimits[2, ] - newlimits[1, ]

# Calculate the new y.major and y.minor relative positions
# and put them along with the new limits back into the build data

N = dim(gd$layout$panel_params)[1]  # Number of panels

for(i in applyTo) {
y.major = (gd$layout$panel_params[[i]]$y.major_source - newlimits[1, i]) / range[i]
y.minor = (gd$layout$panel_params[[i]]$y.minor_source - newlimits[1, i]) / range[i]

gd$layout$panel_params[[i]]$y.range = newlimits[, i]

gd$layout$panel_params[[i]]$y.major = y.major
gd$layout$panel_params[[i]]$y.minor = y.minor
}

# Get the gtable
ggplot_gtable(gd)
}


# Plot it
grid::grid.draw(expand(p, mult = 0.1, applyTo = 1:2))

Original

Modified

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!