PabloAB
PabloAB

Reputation: 243

Spiral bar graph using ggplot2

I'm trying to replicate this plot, particularly the spiral bar chart for INDUSTRIAL. Any idea how to do this using ggplot2? enter image description here

Thanks in advance!

Upvotes: 1

Views: 201

Answers (2)

Allan Cameron
Allan Cameron

Reputation: 174278

The actual code for this is quite straightforward using geomtextpath. It's getting the data in the right format that is difficult:

library(geomtextpath)

df <- data.frame(
  Domain = rep(c("BUSINESS  12", "CLASSICAL  98", "PROFESSIONAL  152",
                 "SCIENTIFIC  161", "NORMAL  383", "INDUSTRIAL  2252"),
               times = c(2, 2, 2, 2, 2, 202)),
  x = c(0, 212, 0, 298, 0, 410, 0, 381, 0, 583, 0,
        800 + 80 * sin(seq(0, pi, length = 100)), 
        80 - 80 * sin(seq(0, pi, length = 100)), 400),
  y = c(8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 
        2.6 + 0.4 * cos(seq(0, pi, length = 100)), 
        1.8 + 0.4 * cos(seq(0, pi, length = 100)), 1.4)
)

ggplot(df, aes(x, y)) + 
  geom_textpath(aes(label = Domain), size = 3,
                colour = "#907f6e", hjust = 0, linewidth = 3.8) + 
  theme_void() + 
  theme(plot.background = element_rect(
    fill = radialGradient(c("#d8cabe", "#ccb5a1"))),
    plot.margin = margin(50, 10, 50, 10))

enter image description here

Upvotes: 8

jdobres
jdobres

Reputation: 11957

As others have pointed out, this is so specific (and so against modern data visualization best practices), that Photoshop is probably the best tool for the job. That said, here's a version that chops up the longest bar into multiple pieces. Not a spiral, but the same basic idea of collapsing a disproportionately large y-axis value by letting it move across the x-axis.

library(tidyverse)

df <- data.frame(
  vocation = c('business', 'classical', 'industrial'),
  enrollment = c(12, 98, 2252)
)

max.bar.size <- 600
df.cut <- df %>% 
  group_by(vocation) %>% 
  summarize(
    bar = 1:(floor(enrollment / max.bar.size) + 1),
    enrollment = c(rep(max.bar.size, floor(enrollment / max.bar.size)), enrollment %% max.bar.size)
  ) %>% 
  mutate(bar = as.character(bar))

ggplot(data = df.cut, aes(x = vocation, y = enrollment, group = bar)) +
  geom_col(position = position_dodge2(preserve = 'single'))

enter image description here

Upvotes: 1

Related Questions