简体   繁体   中英

is it possible to ggplot grouped partial boxplots w/o facets w/ a single `geom_boxplot()`?

I needed to add some partial boxplots to the following plot:

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)

在此处输入图片说明

I would add a grid of (2 x 4 = 8) boxplots (4 per group) to the plot above. Each boxplot should consider a consecutive selection of 25 (or n) points (in each group). Ie, the firsts two boxplots represent the points between the 1st and the 25th (one boxplot below for the group a, and one boxplot above for the group b). Next to them, two other boxplots for the points between the 26th and 50th, etcetera. If they are not in a perfect grid (which I suppose would be both more challenging to obtain and uglier) it would be even better: I prefer if they will "follow" their corresponding smooth line!

That all without using facets (because I have to insert them in a plot which is already facetted :-))

I tried to

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

but it doesn't work.

在此处输入图片说明

I tried to call geom_boxplot() using group instead of x

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

But it draws the boxplots without considering the groups and loosing even the colors (and add a redundant call including color = group doesn't help)

在此处输入图片说明

Finally, I decided to try it roughly:

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

And it works (maintaining even the correct colors from the main aes )! 在此处输入图片说明

Does someone know if it is possible to obtain it using a single call to geom_boxplot() ?

Thanks!

This was interesting! I haven't tried to use geom_boxplot with a continuous x before and didn't know how it behaved. I think what is happening is that setting group overrides colour in geom_boxplot , so it doesn't respect either the inherited or repeated colour aesthetic. I think this workaround does the trick; we combine the group and cut variables into group_cut , which takes 8 different values (one for each desired boxplot). Now we can map aes(group = group_cut) and get the desired output. I don't think this is particularly intuitive and it might be worth raising it on the Github, since usually we expect aesthetics to combine nicely (eg combining colour and linetype works fine).

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'

Created on 2019-08-13 by the reprex package (v0.3.0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM