避免在刻面ggplots中的轴刻度标签冲突

Ben*_*ker 11 r ggplot2 axis-labels

在多面板/刻面图中,我喜欢将面板压在一起并且它们之间没有空间的可行性,例如使用theme(panel.spacing=grid::unit(0,"lines"))(Edward Tufte说这很好,因为面板间空间产生令人分心的视觉效果,以及浪费数据 -太空了,我喝了Kool-Aid的这一点.)

问题在于,取决于小平面的行/列内的值的精确范围,相邻小平面的轴标签可以重叠.例如,在此图中,顶部面板中的底部刻度标签与中间面板中的顶部刻度标签之间存在碰撞.

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)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我想为这个问题构建一个通用,方便的解决方案 - 将每个方面的限制扩展适当的数量(每个方面都会有所不同,因为范围是异构的)但是抑制(至少)标签和(可能)勾选标志着极端的价值观.我过去通过在其中设置专用breaks功能以超级黑客的方式做到了这一点scale_y_continuous.我可能已经考虑过其他一些方法(如果我可以让它们工作,它们会将它们作为答案发布),但我正在寻找(a)用于指定labels和/或的相当强大的通用功能breaks.

与刻面ggplot中的Automate tick max和min不同,它只需要 facet的最大/最小值.

一般来说这很棘手,可能无法完全解决; 我想的只是消除极端标签,但如果只有两个或三个刻度标签,则会失败.可能有一个解决方案expand_limits(),但跨越方面很难做到......

San*_*att 4

编辑更新至 ggplot2 版本 3.0.0

一种可能性可能是修改构建数据。可以采用原始图的限制,并应用乘法展开因子。主次休息的相对位置也需要调整。请注意,该功能允许选择要应用扩展的面板。

expand这和使用inside有什么区别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))
Run Code Online (Sandbox Code Playgroud)

原来的
在此输入图像描述

修改的
在此输入图像描述