将样本大小添加到ggplot中facet的最小值或最大值处的箱形图中

时间:2017-03-15 22:57:28

标签: r ggplot2 facet

关于如何用样本大小标记箱形图,有很多解释,包括this good one。所有这些似乎都使用max(x)median(x)来定位样本大小。

我想知道是否有方法可以轻松地将标签放置在绘图的顶部或底部,尤其是在facet中使用scale = "free_y"命令时,轴的最大值和最小值是通过ggplot自动为每个方面选取。

原因是我创建了多个方面,其中分布很窄,方面很小。如果它位于图的顶部或底部,那么读取样本大小会更容易......但是我想使用" free_y"因为在某些方面存在有意义的差异,这些方面被数据中具有更大跨度的方面所模糊。

使用链接帖子中稍加修改的示例:

# function for number of observations 
give.n <- function(x){
  return(c(y = median(x)*1.05, label = length(x))) 
  # experiment with the multiplier to find the perfect position
}

# function for mean labels
mean.n <- function(x){
  return(c(y = median(x)*0.97, label = round(mean(x),2))) 
  # experiment with the multiplier to find the perfect position
}

# plot
ggplot(mtcars, aes(factor(cyl), mpg, label=rownames(mtcars))) +
  geom_boxplot(fill = "grey80", colour = "#3366FF") +
  stat_summary(fun.data = give.n, geom = "text", fun.y = median) +
  stat_summary(fun.data = mean.n, geom = "text", fun.y = mean, colour = "red") +
  facet_grid(cyl~., scale="free_y")

鉴于此设置,我如何找到每个面的x轴的最小值或最大值,并将样本大小放在那里而不是每个盒子的中间值,最小值或最大值?

修改

我用以下R.S。答案的信息更新问题。目前还没有回答,但是他们的建议提供了在何处查找此信息的解决方案。

ggplot_build(gg)$layout$panel_ranges[[order(levels(factor(mtcars$cyl)))[1]]]$y.range[1]

给出mtcars $ cyl的第一个因子的y范围的最小值。因此,根据我的逻辑,我们需要在没有stat_summary语句的情况下构建绘图,然后使用give.n函数找到样本大小和最小y范围。之后,我们可以将stat_summary语句添加到情节中......如下所示:

# plot
gg = ggplot(mtcars, aes(factor(cyl), mpg, label=rownames(mtcars))) +
  geom_boxplot(fill = "grey80", colour = "#3366FF") +
  facet_grid(cyl~., scale="free_y")

# function for number of observations 
give.n <- function(x){
  return(c(y = ggplot_build(gg)$layout$panel_ranges[[order(levels(factor(mtcars$cyl)))[x]]]$y.range[1], label = length(x))) 
  # experiment with the multiplier to find the perfect position
}

gg +
  stat_summary(fun.data = give.n, geom = "text", fun.y = "median")

但是......上面的代码不起作用,因为我不太了解give.n函数迭代的内容。用1:3中的任何一个替换[[x]]将该方面的所有样本大小绘制为最小值,这样就是进步。

以下是使用[[2]]的图,因此所有样本大小都绘制在17.62,即第二个方面范围的最小值。

enter image description here

1 个答案:

答案 0 :(得分:1)

您可以使用ggplot_build检查ggplot对象的结构,特别是x和y面板范围存储在布局中。将绘图分配给对象并查看结构:

gg <- ggplot(mtcars, aes(factor(cyl), mpg, label=rownames(mtcars))) +
  geom_boxplot(fill = "grey80", colour = "#3366FF") +
  stat_summary(fun.data = give.n, geom = "text", fun.y = median) +
  stat_summary(fun.data = mean.n, geom = "text", fun.y = mean, colour = "red") +
  facet_grid(cyl~., scale="free_y")

  ggplot_build(gg)

特别感兴趣的是:

  ggplot_build(gg)$layout$panel_ranges

3个面板的ylim以c(ymin,ymax)给出并存储在:

 ggplot_build(gg)$layout$panel_ranges[[1]]$y.range
 ggplot_build(gg)$layout$panel_ranges[[2]]$y.range
 ggplot_build(gg)$layout$panel_ranges[[3]]$y.range

编辑回复评论以及如何将此布局信息纳入情节。在这里,我们使用dplyr分别计算cyl分组的统计摘要,并创建单独的数据框以合并到ggplot2中,而不是使用stat_summary

 library(dplyr)
 gg.summary <- group_by(mtcars, cyl) %>% summarise(mean=mean(mpg), median=median(mpg), length=length(mpg))

解析ylim范围并包含到统计摘要df中,统计摘要df按cyl分组,这是我们面临的变量:

 gg.summary$panel.ylim <- sapply(order(levels(factor(mtcars$cyl))), function(x) ggplot_build(gg)$layout$panel_ranges[[x]]$y.range[1])
 # # A tibble: 3 x 5
 # cyl     mean median length panel.ylim
 # <dbl>    <dbl>  <dbl>  <int>      <dbl>
 # 1     4 26.66364   26.0     11     20.775
 # 2     6 19.74286   19.7      7     17.620
 # 3     8 15.10000   15.2     14      9.960

在ggplot中使用,我相信这是你想要的情节:

 gg + geom_text(data=gg.summary, (aes(x=factor(cyl), y=panel.ylim, label=paste("n =",length)))) +
   geom_text(data=gg.summary, (aes(x=factor(cyl), y=median*0.97, label=format(median, nsmall=2))))

enter image description here