ggplot2更改每个小平面面板的轴限制

时间:2018-08-07 21:10:01

标签: r ggplot2

library(tidyverse)
ggplot(mpg, aes(displ, cty)) + 
  geom_point() + 
  facet_grid(rows = vars(drv), scales = "free")

上面的ggplot代码由三个面板4fr组成。我希望每个面板的y轴限制如下:

Panel y-min y-max breaks
----- ----- ----- ------
4     5     25    5
f     0     40    10
r     10    20    2

如何修改我的代码以完成此操作?不确定scale_y_continuous是否更有意义,还是coord_cartesian还是两者的某种组合。

3 个答案:

答案 0 :(得分:2)

这是一个长期存在的功能请求(例如,参见200920112016),由单独的软件包facetscales处理。

devtools::install_github("zeehio/facetscales")
library(g)
library(facetscales)
scales_y <- list(
  `4` = scale_y_continuous(limits = c(5, 25), breaks = seq(5, 25, 5)),
  `f` = scale_y_continuous(limits = c(0, 40), breaks = seq(0, 40, 10)),
  `r` = scale_y_continuous(limits = c(10, 20), breaks = seq(10, 20, 2))
)
ggplot(mpg, aes(displ, cty)) + 
  geom_point() + 
  facet_grid_sc(rows = vars(drv), scales = list(y = scales_y))

enter image description here

如果每个方面的参数都存储在数据帧facet_params中,我们可以根据语言进行计算以创建scale_y

library(tidyverse)
facet_params <- read_table("drv y_min y_max breaks
4     5     25    5
f     0     40    10
r     10    20    2")

scales_y <- facet_params %>% 
  str_glue_data(
    "`{drv}` = scale_y_continuous(limits = c({y_min}, {y_max}), ", 
                "breaks = seq({y_min}, {y_max}, {breaks}))") %>%
  str_flatten(", ") %>% 
  str_c("list(", ., ")") %>% 
  parse(text = .) %>% 
  eval()

答案 1 :(得分:1)

初步

为每个构面的y轴定义原始图和所需参数:

library(ggplot2)
g0 <- ggplot(mpg, aes(displ, cty)) + 
    geom_point() + 
    facet_grid(rows = vars(drv), scales = "free")

facet_bounds <- read.table(header=TRUE,
text=                           
"drv ymin ymax breaks
4     5     25    5
f     0     40    10
r     10    20    2",
stringsAsFactors=FALSE)

版本1:放入虚假数据点

这不符合breaks规范,但它使界限正确:

定义一个新的数据帧,其中包括每个drv的最小值/最大值:

ff <- with(facet_bounds,
           data.frame(cty=c(ymin,ymax),
                      drv=c(drv,drv)))

将它们添加到绘图中(由于xNA不会被绘制,但是它们仍用于定义比例)

g0 + geom_point(data=ff,x=NA)

这与expand_limits()的操作类似,不同之处在于该功能“适用于所有面板或所有图”。

版本2:检测您所在的面板

这很丑陋,取决于每个组都有一个唯一的范围。

library(dplyr)
## compute limits for each group
lims <- (mpg
    %>% group_by(drv)
    %>% summarise(ymin=min(cty),ymax=max(cty))
)

突破功能:弄清楚哪一组对应于它被赋予的极限集...

bfun <- function(limits) {
    grp <- which(lims$ymin==limits[1] & lims$ymax==limits[2])
    bb <- facet_bounds[grp,]
    pp <- pretty(c(bb$ymin,bb$ymax),n=bb$breaks)
    return(pp)
}
g0 + scale_y_continuous(breaks=bfun, expand=expand_scale(0,0))

这里的另一个丑陋之处在于,我们必须设置expand_scale(0,0)来使限制完全等于组限制,这可能不是您想要绘图的方式...

如果可以通过某种方式也传递breaks()函数的信息,那么有关当前正在计算哪个面板的信息...

答案 2 :(得分:0)

我想使用带有刻面刻度的对数刻度并且很费力。

原来,我必须在两个位置指定log10:

scales_x <- list(
  "B" = scale_x_log10(limits=c(0.1, 10), breaks=c(0.1, 1, 10)),
  "C" = scale_x_log10(limits=c(0.008, 1), breaks=c(0.01, 0.1, 1)),
  "E" = scale_x_log10(limits=c(0.01, 1), breaks=c(0.01, 0.1, 1)),
  "R" = scale_x_log10(limits=c(0.01, 1), breaks=c(0.01, 0.1, 1))
)

并在情节中

ggplot(...) + facet_grid_sc(...) +  scale_x_log10()