Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make donut charts with facet_grid in ggplot2?

Tags:

r

ggplot2

I'm trying to make donut charts.

Only problem is they come out looking like this...

enter image description here

Here's my code

ggplot(
  diamonds,
  aes(
    x = cut,
    fill = color
  )
) +
  geom_bar(
    position = 'fill',
    stat = 'bin'
  ) +
  scale_y_continuous(
    labels = percent_format()
  ) +
  facet_grid(clarity ~ cut) + 
  coord_polar(theta = 'y') 

How do I turn my charts from weird pies into circles with the same width?

like image 641
Username Avatar asked Nov 04 '15 20:11

Username


1 Answers

Here's a nice and tidy way to do it:

library(ggplot2)
library(data.table)

# get data, calculate quantities of interest
diam <- diamonds; setDT(diam) 
tabulated <- diam[, .N, by = .(cut, color, clarity)]

# plot
ggplot(tabulated, aes(x=2, y=N, fill=color)) +
  geom_bar(position = 'fill', stat = 'identity')  +
  facet_grid(clarity ~ cut) + 
  xlim(0.5, 2.5) +
  coord_polar(theta = 'y') + 
  labs(x=NULL, y=NULL)

enter image description here

Ok, how does this work? Let's look at your code - you get some plots that look like donuts but with varying hole sizes. Why is that? It's helpful to 'unpie' the data and just look at the output as bars. (I'm going to subset to just two rows of your facets for simplicity.)

ggplot(subset(diamonds, as.numeric(clarity) <=2), 
       aes(x = cut, fill = color)) +
  geom_bar(position = 'fill', stat = 'bin')  +
  facet_grid(clarity ~ cut)

enter image description here

You have a value mapped to X that isn't doing anything useful -- it's offsetting the bars, but since you are faceting on that variable each plot only has one stack of bars in it.

Yet when you add coord_polar, the plots with offset X values show up as donuts, while the plot with x=1 shows up as a pie That's because with coord_polar, the series of stacked bars are nested inside each other, and X=1 means the innermost 'coil'.

So, the solution begins with NOT mapping a real value to X. You can make X=1 for all plots, but then you'll get all pies, not donuts. What you want is a stacked bar, with some space before it on the x-axis (that’ll be the donut hole). You could do this by duplicating the data, so you have two sets stacked bars, then blanking out the first stack. That’s the answer I had up before, and it works (see edit history for details).

Hadley suggested a simpler solution via twitter, though, which I feel obligated to post for posterity: adjust the x limits to force some leading blank space on the x axis.

To begin, calculate the values you want (I'm using data.table for this):

library(data.table)
diam <- diamonds; setDT(diam)
tabulated <- diam[, .N, by = .(cut, color, clarity)]

Now plot, with some room before the stack of bars

enter image description here

There's the stacked bar chart you want, and all you have to do is add coord_polar (as done at the top of the post). You can play with the x limits to tune the donut/hole ratio to your liking.

like image 58
arvi1000 Avatar answered Oct 20 '22 23:10

arvi1000