是否可以使用单个“geom_boxplot()”来对不带分面的分组部分箱线图进行ggplot?

Posted

技术标签:

【中文标题】是否可以使用单个“geom_boxplot()”来对不带分面的分组部分箱线图进行ggplot?【英文标题】:is it possible to ggplot grouped partial boxplots w/o facets w/ a single `geom_boxplot()`? 【发布时间】:2019-08-13 21:56:23 【问题描述】:

我需要在下面的图中添加一些部分箱线图:

library(tidyverse)

foo <- tibble(
  time = 1:100,
  group = sample(c("a", "b"), 100, replace = TRUE) %>% as.factor()
) %>% 
  group_by(group) %>% 
  mutate(value = rnorm(n()) + 10 * as.integer(group)) %>%
  ungroup()

foo %>%
  ggplot(aes(x = time, y = value, color = group)) + 
    geom_point() +
    geom_smooth(se = FALSE)

我会在上面的图中添加一个 (2 x 4 = 8) 个箱线图(每组 4 个)网格。每个箱线图应考虑连续选择 25(或 n)个点(在每组中)。即,前两个箱线图代表第一个和第 25 个之间的点(下面一个箱线图用于 a 组,一个箱线图用于 b 组)。在它们旁边,还有另外两个箱线图,用于 26 日和 50 日之间的点,等等。如果它们不是在一个完美的网格中(我认为这将更具有挑战性并且更丑陋),那就更好了:我更喜欢它们是否会“遵循”它们相应的平滑线!

这一切都没有使用刻面(因为我必须将它们插入到已经刻面的情节中:-))

我试过了

bar <- foo %>%
  group_by(group) %>%
  mutate(cut = 12.5 * (time %/% 25)) %>%
  ungroup()

bar %>%
  ggplot(aes(x = time, y = value, color = group)) + 
    geom_point() +
    geom_smooth(se = FALSE) + 
    geom_boxplot(aes(x = cut))

但它不起作用。

我尝试使用group 而不是x 调用geom_boxplot()

bar %>%
  ggplot(aes(x = time, y = value, color = group)) + 
    geom_point() +
    geom_smooth(se = FALSE) + 
    geom_boxplot(aes(group = cut))

但它在绘制箱线图时不考虑组,甚至丢失颜色(并且添加包括 color = group 在内的冗余调用也无济于事)

最后,我决定粗略地试一试:

bar %>%   
  ggplot(aes(x = time, y = value, color = group)) + 
  geom_point() +
  geom_smooth(se = FALSE) +
  geom_boxplot(data = filter(bar, group == "a"), aes(group = cut)) +
  geom_boxplot(data = filter(bar, group == "b"), aes(group = cut))

而且它可以工作(甚至保持主aes 的正确颜色)!

有人知道是否可以通过调用geom_boxplot() 来获得它吗?

谢谢!

【问题讨论】:

【参考方案1】:

这很有趣!我之前没有尝试将geom_boxplot 与连续的x 一起使用,也不知道它的表现如何。我认为正在发生的事情是设置group 会覆盖geom_boxplot 中的colour,因此它不尊重继承或重复的colour 美学。我认为这种解决方法可以解决问题。我们将groupcut 变量组合成group_cut,它采用8 个不同的值(每个所需的箱线图一个)。现在我们可以映射aes(group = group_cut) 并获得所需的输出。我认为这不是特别直观,可能值得在 Github 上提出,因为通常我们希望美学能够很好地结合(例如结合 colourlinetype 效果很好)。

library(tidyverse)

bar <- tibble(
  time = 1:100,
  group = sample(c("a", "b"), 100, replace = TRUE) %>% as.factor()
) %>% 
  group_by(group) %>% 
  mutate(
    value = rnorm(n()) + 10 * as.integer(group),
    cut = 12.5 * ((time - 1)  %/% 25), # modified this to prevent an extra boxplot
    group_cut = str_c(group, cut)
  ) %>%
  ungroup()

bar %>%
  ggplot(aes(x = time, y  = value, colour = group)) +
  geom_point() +
  geom_smooth(se = FALSE) +
  geom_boxplot(aes(group = group_cut), position = "identity")
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'

由reprex package (v0.3.0) 于 2019-08-13 创建

【讨论】:

它工作正常!我不认为该组会覆盖颜色,否则我的“双重”解决方案不会保留正确的颜色。最令我惊讶的是,我对geom_boxplot() 的两个过滤调用工作正常,每个调用都保持正确的颜色!这就是为什么我不明白一个电话不起作用的原因。我将按照您的建议在 GitHub 上打开一个问题。谢谢! 我想我的意思是group 覆盖了颜色的“分组”方面;在您的双重解决方案中,colour 组和group 组恰好对齐。但它确实感觉像是一些实现细节

以上是关于是否可以使用单个“geom_boxplot()”来对不带分面的分组部分箱线图进行ggplot?的主要内容,如果未能解决你的问题,请参考以下文章

geom_boxplot 作为直方图中的插图

ggplot geom_boxplot 用于基因表达数据

更改 geom_boxplot 中的晶须定义

R语言使用ggplot2包使用geom_boxplot函数绘制基础分组箱图(输出多个分组)实战

R语言使用ggplot2包使用geom_boxplot函数绘制基础分组水平箱图(boxplot)实战

R语言使用ggplot2包使用geom_boxplot函数绘制基础分组箱图(配置显示的分组)实战