'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:

here

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)

enter image description here

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"))

enter image description here

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