在多面板/多面图中,我喜欢将面板挤压在一起并且它们之间没有空间的可行性,例如:使用theme(panel.spacing=grid::unit(0,"lines"))
(Edward Tufte说这很好,因为小组间空间产生了令人分心的视觉效果,以及浪费数据空间,而且我已经喝了Kool-Aid的这一点。)< / p>
问题在于,根据构面的行/列内的值的精确范围,相邻构面的轴标签可以重叠。例如,在此图中,顶部面板中的底部刻度标签与中间面板中的顶部刻度标签之间存在碰撞。
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)
ggplot(dd,aes(x,y))+
facet_grid(f~.,scale="free")+
geom_point()+
theme_bw(base_size=24)+
theme(panel.spacing=grid::unit(0,"lines"))
ggsave("tmp1.png",width=4,height=6)
我想为这个问题构建一个通用,方便的解决方案 - 将每个方面的限制扩展一个适当的数量(对于每个方面,它将是不同的,因为范围是异构的)但是抑制(至少)标签和(可能)极值的刻度线。我过去通过在breaks
内设置专用scale_y_continuous
功能,以超级黑客的方式做到了这一点。我可能已经想到了其他一些方法(如果我可以让它们工作,我会将它们作为答案发布),但我正在寻找(a)用于指定{{}的相当强大的通用函数。 1}}和/或labels
。
这与Automate tick max and min in faceted ggplot不同,{{3}}只需要facet的最大/最小值。
一般来说这很棘手,可能无法完全解决;我想的只是消除极端标签,但如果只有两个或三个刻度标签,则会失败。可能有breaks
的解决方案,但跨方面很难做到......
答案 0 :(得分:4)
编辑已更新为ggplot2 ver 3.0.0
一种可能是修改构建数据。可以采用原始图的限制,并应用乘法扩展因子。主要和次要休息的相对位置也需要调整。请注意,该功能允许选择要应用扩展的面板。
在expand
中使用scale_y_continuous
之间的区别是什么(除了能够选择面板之外)?此函数保留原始中断(以及刻度线和网格线)。只是他们占用的空间更少。但是,expand
将压缩比例,但ggplot会添加新标签,网格线和刻度线(如果可以)。
破坏函数不会花费太多时间 - 已知ggplot会更新最新版本中构建数据的元素名称。
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))