避免多面ggplots中的轴刻度标签碰撞 [英] Avoiding axis tick label collision in faceted ggplots

查看:87
本文介绍了避免多面ggplots中的轴刻度标签碰撞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在多面板/多面情节中,我喜欢将面板挤压在一起且它们之间没有空间的情况,例如使用theme(panel.spacing=grid::unit(0,"lines"))(Edward Tufte表示这很好,因为面板间的空间会产生分散注意力的视觉效果,并且浪费数据空间,而且我已经喝掉了Kool-Aid的这一特定部分.)

In multi-panel/faceted plots, I like when it's feasible to squash the panels together with no space between them, e.g. using theme(panel.spacing=grid::unit(0,"lines")) (Edward Tufte says this is good because the inter-panel spaces produce distracting visual effects, as well as wasting data-space, and I've drunk this particular bit of the Kool-Aid.)

问题在于,取决于小平面的行/列中值的精确范围,相邻小平面的轴标签可能会重叠.例如,在该图中,顶部面板的底部刻度标签和中间面板的顶部刻度标签之间发生冲突.

The problem is that, depending on the precise range of the values within a row/column of facets, the axis labels for neighboring facets can overlap. For example, in this plot there's a collision between the bottom tick label in the top panel and the top tick label in the middle panel.

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)

我想为这个问题建立一个通用,方便的解决方案-将每个构面的限制扩展一个适当的数量(每个构面会有所不同,因为范围是不同的),但是抑制了(至少)极值的标签和(可能)刻度线.过去,我通过在scale_y_continuous中设置特殊用途的breaks函数来以超级黑客的方式完成此操作.我可能已经想到了其他方法来执行此操作(如果可以使它们工作,将把它们作为答案发布),但是我正在寻找(一个)相当健壮的通用函数来指定labels和/或breaks.

I want to build a general, convenient solution to this problem - extending the limits of each facet by an appropriate amount (it will be different for each facet, since the ranges are heterogeneous) but suppressing (at least) labels and (possibly) tick marks for the extreme values. I've done this in the past in a super-hacky way by setting a special-purpose breaks function within scale_y_continuous. I may have thought of some other ways to do this (and will post them as an answer if I can get them to work), but I'm looking for (a) reasonably robust general function(s) for specifying labels and/or breaks.

这与将刻面中的最大和最小刻度线自动化ggplot ,它只是需要按构面的最大值/最小值.

This is not the same as Automate tick max and min in faceted ggplot , which just wants the max/min values by facet.

这通常很难完成,可能无法完全解决.我考虑过只消灭极端标签,但是如果只有两个或三个刻度标签,那将失败. expand_limits()可能有解决方案,但这很难在各个方面实现...

This is tricky to do in general and might not be completely solvable; I thought about just blanking out the extreme labels, but that would fail if there were only two or three tick labels. There might be a solution with expand_limits(), but that's hard to do across facets ...

推荐答案

编辑已更新至ggplot2 3.0.0版

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.

这与在scale_y_continuous中使用expand有什么区别(除了能够选择面板)?此功能使中断(以及刻度线和网格线)保持原始状态.只是它们占用的空间更少.但是,expand将压缩比例,但ggplot会添加新标签,网格线和刻度线.

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.

破坏该功能不会花费太多-已知ggplot可以在最新版本中更改构建数据的元素名称.

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))

原始

已修改

这篇关于避免多面ggplots中的轴刻度标签碰撞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆