Home > Net >  modify horizontal barplots for combination (tight design)
modify horizontal barplots for combination (tight design)

Time:03-23

I have the following sample data:

library(tidyverse)

df <- data.frame(col=rep(c("A_B", "A_C", "A_D", 
                           "B_A", "C_A", "D_A",
                           "B_C", "B_D", 
                           "C_B", "D_B",
                           "C_D", "D_C"), 2),
                 level=c(rep("lower_level", 12), rep("higher_level", 12)),
                 value=abs(rnorm(24, mean=5, sd=2)))%>% tibble()
df[c('origin', 'target')] <- str_split_fixed(df$col, '_', 2)
df <- df %>% select(c(origin, target, level, value))

I now want to create horizontal stacked barplots for each target (df %>% filter(target=="A")). I do this using the following code:

# plot
p1 <- ggplot(data = df %>% filter(target=="A"), 
            aes(x = factor(level), y = value, fill = factor(origin))) 
  geom_bar(stat="identity", position="fill", width = .1)   
  scale_fill_manual(values = c("A"="yellow", "B" = "green", "C"="red", "D"="blue"))  
  coord_flip()

Since I want to combine multiple such plots later (s. below), I would like to

  1. remove the empty space between y-axis and the bars (or manipulate it to value X)

  2. have the fill label displayed on the right side

  3. have one value on the left, saying "target: A"

  4. and have fill legend and y axis shared between all plots.

See annotated plot:

barplot

For reference, I create additional plots with this code:

p2 <- ggplot(data = df %>% filter(target=="B"), 
       aes(x = factor(level), y = value, fill = factor(origin))) 
  geom_bar(stat="identity", position="fill", width = .1)  
  scale_fill_manual(values = c("A"="yellow", "B" = "green", "C"="red", "D"="blue"))  
  coord_flip()

p3 <- ggplot(data = df %>% filter(target=="C"), 
             aes(x = factor(level), y = value, fill = factor(origin))) 
  geom_bar(stat="identity", position="fill", width = .1)  
  scale_fill_manual(values = c("A"="yellow", "B" = "green", "C"="red", "D"="blue"))  
  coord_flip()

p4 <- ggplot(data = df %>% filter(target=="D"), 
             aes(x = factor(level), y = value, fill = factor(origin))) 
  geom_bar(stat="identity", position="fill", width = .1)  
  scale_fill_manual(values = c("A"="yellow", "B" = "green", "C"="red", "D"="blue"))  
  coord_flip()

And combine them with this code (but happy to use other ways of combining them if needed).

library("gridExtra")
grid.arrange(p1, p2, p3, p4, ncol = 1, nrow = 4)

CodePudding user response:

It sounds very much as though you simply want to facet by target. No need for stitching multiple plots here.

ggplot(data = df %>% mutate(target = paste('Target:', target)), 
             aes(x = factor(level), y = value, fill = factor(origin))) 
  geom_col(position = "fill", width = 0.9)   
  scale_fill_manual(values = c("A"="yellow", "B" = "green", 
                               "C"="red", "D"="blue"), name = 'origin')  
  facet_grid(target~., switch = 'y')  
  coord_flip()  
  theme(strip.placement = 'outside',
        strip.background = element_blank(),
        axis.title.y = element_blank())

enter image description here

CodePudding user response:

two suggestions_

  1. to remove the offset between axis and bar, set the axis expansion to zero scale_x_continuous(..., expand = c(0,0))
  2. instead of tediously subsetting the data frame, use the facet_wrap or facet_grid option of ggplot:
ggplot(data = df, 
             aes(x = factor(level), y = value, fill = factor(origin)))  
       ## other plot instructions
       facet_wrap( ~target)

see ?facet_wrap for various layout options like number of plot columns 3. the vertical spacing between bars will be adjusted to the output dimensions (here: figure height) anyway

  • Related