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
remove the empty space between y-axis and the bars (or manipulate it to value
X
)have the
fill
label displayed on the right sidehave one value on the left, saying "target: A"
and have
fill
legend and y axis shared between all plots.
See annotated plot:
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())
CodePudding user response:
two suggestions_
- to remove the offset between axis and bar, set the axis expansion to zero
scale_x_continuous(..., expand = c(0,0))
- instead of tediously subsetting the data frame, use the
facet_wrap
orfacet_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