Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pie chart ggplot: text directions and graphics are different

Tags:

r

ggplot2

I have a dataset like this

data=data.frame(Var1 = c('a', 'b'), Freq=c(31, 48))

And I want to make a ggplot pie chart. I do this as below

library(ggplot2)
tbl <- transform(data,
                 freq = cumsum(Freq),
                 perc = Freq/sum(Freq),
                 pos = (cumsum(Freq) - 0.5 * Freq) / sum(Freq))
ggplot(data=tbl, aes(x="", y=perc, fill = factor(Var1))) + 
  geom_bar(width = 0.8, stat="identity") + 
  coord_polar(theta="y",start = 0,  direction = 1) +
  geom_text(aes(label=paste(round(perc*100),"%",sep=""), y=pos), 
            color="grey20" ,size=15) +
  scale_fill_manual(tbl$Var1,values = c("coral2", "red")) + 
  theme_bw() + 
  theme (panel.border = element_blank(),legend.title = element_blank(),
         axis.ticks = element_blank(),axis.title.x = element_blank(), 
         axis.title.y = element_blank(), axis.text.x = element_blank(),
         axis.line=element_blank(),panel.grid.major=element_blank(),
         legend.background = element_rect(fill="transparent"), legend.position=c(0.5,0.1), 
         legend.direction="vertical", legend.text=element_text(size = 20)) 

I get the pie chart enter image description here

As you can see text directions and graphics are different. And I use coord_polar(theta="y",start = 0, direction = 1) that direction = 1 means the clockwise direction. But actually direction of pies is anticlockwise. What I do wrong?

like image 259
Edward Avatar asked Oct 20 '25 14:10

Edward


1 Answers

Your problem lies with how you calculated the text positions. It has nothing to do with polar coordinates.

Let's take a look at the dataframe created from transforming data:

> tbl
  Var1 Freq freq      perc       pos
1    a   31   31 0.3924051 0.1962025
2    b   48   79 0.6075949 0.6962025

ggplot(data=tbl, aes(x="", y=perc, fill = factor(Var1))) + 
  geom_bar(width = 0.8, stat="identity") + 
  geom_text(aes(label=paste(round(perc*100),"%",sep=""),y=pos), color="grey20" ,size=15)

plot

These are clearly not the intended positions for the text labels. Manually calculating the label positions of a stacked bar chart isn't completely trivial, but you can actually let ggplot do the work for you, using position_stack() and specifying your preferred vjust value. Here's an implementation:

ggplot(data = tbl,
       aes(x = "", y = perc, fill = Var1)) +
  geom_col() +
  geom_text(aes(label = scales::percent(perc, accuracy = 1)),
            position = position_stack(vjust = 0.5),
            color = "grey20", size = 15) +
  coord_polar(theta = "y", direction = -1) +
  scale_fill_manual(values = c("a" = "coral2", "b" = "red")) +
  theme_void() +
  theme(legend.position = "bottom",
        legend.direction = "vertical")

Other things to note for the above code:

  1. Use geom_col() instead of geom_bar(stat = "identity"); they are equivalent and the former looks cleaner;

  2. Use percent() from the scales package to create percent labels; it's more intuitive than messing around with round() & paste() yourself;

  3. coord_polar() has start = 0 and direction = 1 as its default parameters. If you aren't changing the default, you don't have to specify them;

  4. It's usually safer to use a named vector to specify mapping values in a manual scale, in case you use the same code across multiple datasets, and not all the values appear in every case;

  5. If you find yourself repeating XXX = element_blank() numerous times, it's probably time to switch to theme_void() & only specify exceptions to the rule.

plot

like image 123
Z.Lin Avatar answered Oct 22 '25 02:10

Z.Lin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!