'Creating a dual bar chart
I'm looking to create a bar char similar to the example below, although I don't know the name or code used for this. I'm looking to get a horizontal bar char with PM2.5 to the left and life expectancy to the right of my continents labeled down the middle. My data and example of what I want it to look like below.
Image of what i want my graph to look like:

My data:
life_bar
# A tibble: 6 × 2
Continent mn
<chr> <dbl>
1 Africa 62.7
2 Americas 74.8
3 Eastern Mediterranean 71.3
4 Europe 78.1
5 South-East Asia 71.6
6 Western Pacific 74.3
> air_pollution_bar
# A tibble: 6 × 2
Continent mn
<chr> <dbl>
1 Africa 41.1
2 Americas 19.5
3 Eastern Mediterranean 47.0
4 Europe 15.6
5 South-East Asia 37.7
6 Western Pacific 16.4
Solution 1:[1]
This should get you started:
## please make sample data availabe, e.g. by pasting the output of `dput(df)`
life_bar <- structure(list(cty = c("Africa", "Americas", "Eastern Mediterranean",
"Europe", "South-East Asia", "Western Pacific"), val = c(62.7,
74.8, 71.3, 78.1, 71.6, 74.3)), class = "data.frame", row.names = c(NA,
6L))
structure(list(cty = c("Africa", "Americas", "Eastern Mediterranean",
"Europe", "South-East Asia", "Western Pacific"), val = c(41.1,
19.5, 47, 15.6, 37.7, 16.4)), class = "data.frame", row.names = c(NA,
6L))
## the actual code example:
life_bar %>%
ggplot() +
geom_col(aes(cty, val), fill = NA, colour = 'blue') +
geom_col(data = air_pollution_bar, aes(cty,val), fill = 'red') +
scale_x_discrete(limits = rev) + ## reverse country axis
coord_flip() ## make horizontal bars
So, technically it's rather simple, if(!) you want to display data with apperently different units along the same axis ;-)
Solution 2:[2]
What you are looking for is called side-by-side bar.
A quick solution:
Sample data:
df<-structure(list(Continent = structure(c(1L, 2L, 3L, 4L, 5L, 6L,
1L, 2L, 3L, 4L, 5L, 6L), .Label = c("Africa", "Americas", "Easstern Mediterranean",
"Europe", "Sout-East Asia", "Western Pacific"), class = "factor"),
mn = c(62.7, 74.8, 71.3, 78.1, 71.6, 74.3, 41.1, 19.5, 47,
15.6, 37.7, 16.4), Condition = c("life_bar", "life_bar",
"life_bar", "life_bar", "life_bar", "life_bar", "air_pollution",
"air_pollution", "air_pollution", "air_pollution", "air_pollution",
"air_pollution")), spec = structure(list(cols = list(Continent = structure(list(), class = c("collector_character",
"collector")), mn = structure(list(), class = c("collector_double",
"collector")), Condition = structure(list(), class = c("collector_character",
"collector"))), default = structure(list(), class = c("collector_guess",
"collector")), delim = ","), class = "col_spec"), problems = <pointer: 0x1d498f30>, row.names = c(NA,
-12L), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
))
Continent<-c("Africa","Americas","Easstern Mediterranean", "Europe", "Sout-East Asia", "Western Pacific")
df$Continent = factor(df$Continent, levels=c("Africa","Americas","Easstern Mediterranean", "Europe", "Sout-East Asia", "Western Pacific"))
Common theme:
#Common theme
theme = theme(panel.grid.minor = element_blank(),
panel.grid.major = element_blank(),
axis.text.y = element_blank(),
axis.title.y = element_blank(),
plot.title = element_text(size = 10, hjust = 0.5))
#"Life_bar" plot - to appear on the right
ggL<- ggplot(data = subset(df, Condition == 'life_bar'), aes(x=Continent)) +
geom_bar(aes(y = mn/100, fill = mn), stat = "identity") +
scale_y_continuous('', labels = percent, limits = c(0, 1), expand = c(0,0)) +
labs(x = NULL) +
ggtitle("Life_Bar") +
coord_flip() + theme +
theme(plot.margin= unit(c(1, 0, 0, 0), "lines"))
gtL <- ggplotGrob(ggL)
#The legend
leg = gtL$grobs[[which(gtL$layout$name == "guide-box")]]
#Back to "life_bar" plot - to appear on the right and remove legend
legPos = gtL$layout$l[grepl("guide", gtL$layout$name)] # legend's position
gtL = gtL[, -c(legPos-1,legPos)]
#"Air_pollution" plot - to appear on the left reverse the 'Percent' axis using trans = "reverse"
ggA <- ggplot(data = subset(df, Condition == 'air_pollution'), aes(x=Continent)) +
geom_bar(aes(y = mn/100, fill = mn), stat = "identity") +
scale_y_continuous('', labels = percent, trans = 'reverse',
limits = c(1, 0), expand = c(0,0)) +
labs(x = NULL) +
ggtitle("Air_pollution") +
coord_flip() + theme +
theme(plot.margin= unit(c(1, 0, 0, 1), "lines"))
#ggplot grob and remove legend
gtA <- ggplotGrob(ggA)
gtA = gtA[, -c(legPos-1,legPos)]
#Tick marks to the right side of the plot panel
rn <- which(gtA$layout$name == "axis-l")
#Extract the axis (tick marks and axis text)
a
xis.grob <- gtA$grobs[[rn]]
axisl <- axis.grob$children[[2]]
#Get the tick marks
yaxis = axisl$grobs[[2]]
yaxis$x = yaxis$x - unit(1, "npc") + unit(2.75, "pt")
#Add them to the right side of the panel
panelPos = gtA$layout[grepl("panel", gtA$layout$name), c('t','l')]
gtA <- gtable_add_cols(gtA, gtA$widths[3], panelPos$l)
#Add the grob
gtA <- gtable_add_grob(gtA, yaxis, t = panelPos$t, l = panelPos$l+1)
#Remove original left axis
gtA = gtA[, -c(2,3)]
#Continent labels
fontsize = 5
ggC <- ggplot(data = subset(df, Condition == 'air_pollution'), aes(x=Continent)) +
geom_bar(stat = "identity", aes(y = 0)) +
geom_text(aes(y = 0, label = Continent), size = fontsize) +
ggtitle("Continent") +
coord_flip() + theme_bw() + theme +
theme(panel.border = element_rect(colour = NA))
#get ggplot grob
gtC <- ggplotGrob(ggC)
#Get the title
Title = gtC$grobs[[which(gtC$layout$name == "title")]]
#Get the plot panel
gtC = gtC$grobs[[which(gtC$layout$name == "panel")]]
#Combine "air_pollution" and "life_bar" plots
gt = cbind(gtA, gtL, size = "first")
#Add the labels (gtC) down the middle and add column to table
maxlab = Continent[which(str_length(Continent) == max(str_length(Continent)))]
gt = gtable_add_cols(gt, sum(unit(1, "grobwidth", textGrob(maxlab, gp = gpar(fontsize = fontsize*72.27/25.4))), unit(5, "mm")),
pos = length(gtA$widths))
#add the grob
gt = gtable_add_grob(gt, gtC, t = panelPos$t, l = length(gtA$widths) + 1)
#add the title; ie the label 'continent'
titlePos = gtA$layout$l[which(gtA$layout$name == "title")]
gt = gtable_add_grob(gt, Title, t = titlePos, l = length(gtA$widths) + 1)
#Add the legend to the right
gt = gtable_add_cols(gt, sum(leg$width), -1)
gt = gtable_add_grob(gt, leg, t = panelPos$t, l = length(gt$widths))
#draw the plot
grid.newpage()
grid.draw(gt)
Another solution would be:
ggplot(df, aes(x=Continent, y= mn, fill=Condition)) +
#facet_wrap(~ Condition, scales = "free_x") +
geom_col() +
coord_flip() +
scale_y_continuous(expand = c(0, 0)) +
theme(panel.spacing.x = unit(0, "mm"))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | I_O |
| Solution 2 |


