首页 文章

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

提问于
浏览
0

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

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

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

使用链接帖子中略微修改的示例:

# 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轴的最小值或最大值,并在那里定位样本大小而不是每个盒子的中间值,最小值或最大值?

EDIT

我正在用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 回答

  • 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

相关问题