The same area for all violins, regardless of the edges in ggplot2

I want to create a plot for three different factors, where all the violins have the same area. But use facet_grid(. ~ C), apparently, makes the screens in every aspect (i.e., only those within the factor C level) have the same area. How can I overcome this?

library(ggplot2)

d <- data.frame(value = c(906, 1013, 1109, 876, 747, 759, 876, 1358, 739, 
                          1086, 807, 954, 1586, 762, 1353, 1221, 976, 1002, 
                          1129, 943, 1270, 1126, 853, 950, 677, 696, 681, 
                          615, 736, 595, 590, 618, 524, 1014, 515, 645, 860, 
                          874, 934, 728, 1078, 659, 1024, 786, 821, 541,
                          681, 744),
                A = gl(2, 12, 48),
                B = gl(2, 6, 48),
                C = gl(2, 24))

ggplot(d, aes(x = A, y = value, fill = B)) +
  geom_violin(trim = FALSE, scale = "area") +
  facet_grid(. ~ C)

enter image description here

+4
source share
2 answers

First we create a new one data.framewith pre-calculated densities:

library('tidyverse')

d2 <- d %>%
  group_by(A, B, C) %>%
  do({
    dens <- density(.$value)
    tibble(x = c(head(dens$x, 1), dens$x, tail(dens$x, 1)), #Add 0s at end to close lines
           y = c(0, dens$y, 0))
  }) %>% 
  ungroup() %>% 
  mutate(ymin = as.numeric(A:B) - .4*y/max(y), # Add offset for factor levels
         ymax = as.numeric(A:B) + .4*y/max(y))

And now we will build densities in the form of tapes:

ggplot(d2)+
  aes(x = x,
      ymin = ymin,
      ymax = ymax,
      group = A:B,
      fill = B)+
  geom_ribbon()+

  # Enclosing lines
  geom_line(aes(y = ymin))+
  geom_line(aes(y = ymax))+

  facet_grid(. ~ C)+

  scale_y_continuous(breaks = c(1.5, 2.5),
                     minor_breaks = c(1.5, 3.5),
                     labels = levels(d2$A))+

  labs(x = 'value', y = 'A')+
  coord_flip()

enter image description here

+1
source
Both of the below give the same plot as the faceted one:

ggplot(d, aes(x = paste(C,A), y = value, fill = B)) +
geom_violin(trim = FALSE, scale = "area") 

ggplot(d, aes(x =  C:A, y = value, fill = B)) +
geom_violin(trim = FALSE, scale = "area")

Well, if you can describe the purpose of your plot. Since other approaches may serve your purpose better than back to back density or ggridges :: geom_density_ridges2:

ggplot(d,
aes(x = value, y = paste(A,B), fill = B, height = ..density..))+
ggridges::geom_density_ridges2(scale = 1.2,alpha=0.2,stat = "density")+
facet_grid(. ~ C)+
ggridges::theme_ridges()+
coord_flip()
0
source

Source: https://habr.com/ru/post/1688923/


All Articles