4

I am using R and ggplot2 to do some plots for publishing purposes. I have come across this plot and I would like to replicate it using ggplot2. However, I have never seen a plot like this made using ggplot2.

Can it be done with ggplot2? What about the text below the bars? I guess these will have to be hard coded in the ggplot2 codes. And how do you align those text?

Bar graph

user3115933
  • 4,303
  • 15
  • 54
  • 94

3 Answers3

9

This gets fairly close:

# Generate sample data (I'm too lazy to type out the full labels)
df <- data.frame(
    perc = c(60, 36, 44, 41, 42, 57, 34, 52),
    type = rep(c("blue", "green"), 4),
    label = rep(c(
        "Individual reports created as needed",
        "Regular reports on single topics",
        "Analytics using data integrated from multiple systems",
        "Business unit-specific dashboards and visuals"), each = 2))


library(ggplot2)
ggplot(df, aes(1, perc, fill = type)) +
    geom_col(position = "dodge2") +
    scale_fill_manual(values = c("turquoise4", "forestgreen"), guide = FALSE) +
    facet_wrap(~ label, ncol = 1, strip.position = "bottom") +
    geom_text(
        aes(y = 1, label = sprintf("%i%%", perc)),
        colour = "white",
        position = position_dodge(width = .9),
        hjust = 0,
        fontface = "bold") +
    coord_flip(expand = F) +
    theme_minimal() +
    theme(
        axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        strip.text = element_text(angle = 0, hjust = 0, face = "bold"))

enter image description here

A few explanations:

  1. We use dodged bars and matching dodged labels with position = "dodge2" (note that this requires ggplot_ggplot2_3.0.0, otherwise use position = position_dodge(width = 1.0)) and position = position_dodge(width = 0.9), respectively.
  2. We use facet_wrap and force a one-column layout; strip labels are moved to the bottom.
  3. We rotate the entire plot with coord_flip(expand = F), where expand = F ensures that left aligned (hjust = 0) facet strip texts align with 0.
  4. Finally we tweak the theme to increase the overall aesthetic similarity.
Maurits Evers
  • 49,617
  • 4
  • 47
  • 68
  • Excellent answer! – user3115933 Aug 30 '18 at 12:30
  • @user3115933 Thanks, this was fun:-) – Maurits Evers Aug 30 '18 at 12:34
  • I copied your exact codes to run it at my end in RStudio and I am getting the following error message: Error: Found object is not a position. What could be wrong? – user3115933 Aug 30 '18 at 13:04
  • @user3115933 Strange; what is your `ggplot` version? I tried this on `ggplot2_3.0.0` and I can't reproduce the error. You'd have to go through the different plot components to see which line throws the error. Or probably easier, update `ggplot2`. – Maurits Evers Aug 30 '18 at 13:10
  • ggplot2_2.2.1 When I change position ="dodge2" to position = "dodge", it works correctly but then I lose the gap between the bars! – user3115933 Aug 30 '18 at 13:13
  • @user3115933 Ah. I think I know. It's the `position = "dodge2"` argument in `geom_col` (which was introduced in version 3 of `ggplot2`). – Maurits Evers Aug 30 '18 at 13:13
  • 1
    @user3115933 As an alternative to `position = "dodge"` you can also use `position = position_dodge(width = 1)` inside `geom_col`. I made an edit in my answer to clarify. – Maurits Evers Aug 30 '18 at 13:15
4

You can try using the data from the other answer. Differences are: we use scales::percent to draw percents. We use ggpubr::theme_transparent() theme to tweak as less as possible.

df$perc <- c(.60, .36, .44, .41, .42, .57, .34, .52)

ggplot(df, aes(label, perc, label=scales::percent(round(perc,2)),fill= factor(type))) + 
   geom_col(position = position_dodge(0.9), show.legend = F) + 
   geom_text(aes(y=0), position = position_dodge(0.9), size=5, hjust=-0.1, color="white", fontface="bold") +
   scale_y_continuous("",labels = scales::percent) + 
   coord_flip(expand = F) + 
   facet_wrap(~label,scales = "free", strip.position = "bottom", ncol = 1) +
   ggpubr::theme_transparent() +
   xlab("") + 
   theme(strip.background = element_blank(),
         strip.text = element_text(size = 12, face = "bold",hjust=0))

enter image description here

Roman
  • 17,008
  • 3
  • 36
  • 49
0

Maybe using facet wrap and adjusting the style?

dat <- data.frame(perc = c(60, 20, 90, 30), col = rep(c("gr1", "gr2"), 2),
                  text = c(rep("text1", 2), rep("text2", 2)))

ggplot(dat, aes(y = perc, x = col, fill = col)) +
  geom_bar(stat = "identity", position = "dodge") +
  coord_flip() +
  facet_wrap(~text, strip.position = "bottom", ncol = 1)
RobertE
  • 1
  • 1