njudd / ggrain

{package} Make beautiful Raincloud plots in R!
Other
67 stars 4 forks source link

geom_rain, flanking & facet_wrap #7

Closed hille closed 1 year ago

hille commented 1 year ago

Hello! I have a similar problem as mentioned here https://github.com/njudd/ggrain/issues/6#issuecomment-1518993600 How is it possible to change the position of either the two middle violins (using rain.side = "f1x1" ) or the two middle boxplots (using rain.side = "f2x2")?

fake_d <- tibble(ID = rep(1:30,each=2), 
                 Group = factor(rep(c("young","old"),each=2, times=15)),
                 Time =  factor(rep(c("T1", "T2"),times=30)),
                 Response = rnorm(60))

fake_d %>% 
  ggplot(aes(x=Time,y=Response, fill=Time))+
  geom_rain(id.long.var = "ID", rain.side='f1x1',
            violin.args = list(color = NA,alpha = .7),
            alpha = .7) +
  facet_wrap(~Group)

image

fake_d %>% 
  ggplot(aes(x=Time,y=Response, fill=Time))+
  geom_rain(id.long.var = "ID", rain.side='f2x2',
            violin.args = list(color = NA,alpha = .7),
            alpha = .7) +
  facet_wrap(~Group)

image

njudd commented 1 year ago

They're two solutions to this issue: 1) using patchwork or 2) manually positioning the elements. Manual positioning is shown at the end of the vignette.

1) Patchwork

library(patchwork); library(ggrain)

old <- ggplot(fake_d[fake_d$Group == 'old',], aes(x=Time, y=Response, fill = Time)) +
  geom_rain(id.long.var = 'ID', rain.side = 'f1x1')
young <- ggplot(fake_d[fake_d$Group == 'young',], aes(x=Time, y=Response, fill = Time)) +
  geom_rain(id.long.var = 'ID', rain.side = 'f1x1')

ptchd <- old + young + plot_layout(guides = "collect") & theme(legend.position = "right")

ptchd

2) Manually

manual_position <- ggplot(fake_d, aes(x=Time, y=Response, fill = Time)) +
  geom_rain(rain.side = 'f', id.long.var = "ID",
            boxplot.args.pos = list(width = .1, # you have 4 elements, ordered left to right; since they are facetted we need to flip the sign
                                    position = ggpp::position_dodgenudge(x = c(-.13, .13, # t1 old, t2 old
                                                                               -.13, .13))), # t1 young, t4 young
            violin.args.pos = list(width = .7,
                                   position = position_nudge(x = c(rep(-.2, 256*2), rep(-.2, 256*2), #t1 old, t1 young
                                                                   rep(.2, 256*2), rep(.2, 256*2))))) + #t2 old, t2 young
  facet_wrap(~Group)
manual_position
hille commented 1 year ago

Thank you so much! I prefer to use the manual adjustment because I would like to take advantage of some facet_wrap options (e.g. automatic common x- and y-axis and facet labels). Could you explain to me why one needs 256*2 values for one violin?

njudd commented 1 year ago

It's an internal feature of the density estimation (see ?density; n = 512) for the violin and is arbitrary.

Now why it is 256*2 and not 512 is probably legacy code from me doing this; which will make it clearer exactly what the nudging is doing:

ggplot(fake_d[fake_d$Group == 'old',], aes(x=Time, y=Response, fill = Time)) +
  geom_rain(id.long.var = 'ID', rain.side = 'f',
            boxplot.args = list(color = NA, fill = NA), # getting rid of the boxplots
            violin.args.pos = list(width = .7,
                                   position = position_nudge(x = c(rep(-.2, 512), rep(.2, 512)))))

Rplot

ggplot(fake_d[fake_d$Group == 'old',], aes(x=Time, y=Response, fill = Time)) +
  geom_rain(id.long.var = 'ID', rain.side = 'f',
            boxplot.args = list(color = NA, fill = NA), # getting rid of the boxplots
            violin.args.pos = list(width = .7,
                                   position = position_nudge(x = c(rep(-.2, 256), rep(.2, 256), 
                                                                   rep(-.2, 256), rep(.2, 256)))))

Rplot011

hille commented 1 year ago

Makes sense, thank you :)