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
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?
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)
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:
Use geom_col()
instead of geom_bar(stat = "identity")
; they are equivalent and the former looks cleaner;
Use percent()
from the scales
package to create percent labels; it's more intuitive than messing around with round()
& paste()
yourself;
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;
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;
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With