Reputation: 1528
I made a pie chart using R and ggplot2, more or less according to example #128 of the R Graph Gallery.
piePlot <- function(count, categories) {
dat <- data.frame(count = count, category = categories)
dat$fraction <- dat$count / sum(dat$count)
dat$ymax <- cumsum(dat$fraction)
dat$ymin <- c(0, head(dat$ymax, n = -1))
dat$label <- paste(dat$category, dat$count)
plot <-
ggplot(dat, aes(
fill = category,
ymax = ymax,
ymin = ymin,
xmin = 0,
xmax = 1
)) +
geom_rect() +
coord_polar(theta = "y") +
scale_fill_brewer(labels = dat$label, guide = "legend")
plot
}
piePlot(count = c(20, 10, 30),
categories = c("one", "two", "three"))
Here's the output:
The colors of the legend mismatch. The biggest are is supposed to be the darkest (three 30) according to the legend, which is obviously not the case. Here's a printout of my data frame right before the plot:
count category fraction ymax ymin label
1 20 one 0.3333333 0.3333333 0.0000000 one 20
2 10 two 0.1666667 0.5000000 0.3333333 two 10
3 30 three 0.5000000 1.0000000 0.5000000 three 30
This is exactly the legend's order, but ggplot seems to reorder the fields somehow when doing the plot. I just cannot understand why.
I'm using R version 3.4.2 and ggplot2 version 2.2.1.
Does anybody know how and why this reordering is taking place, and how I could suppress it?
Upvotes: 1
Views: 411
Reputation: 26343
The mismatch occurs because ggplot()
orders the legend alphabetically in the first place, i.e. the legend entries would read "one 20, three 30, two 10" from top to bottom if you would not have called scale_fill_brewer
But you overwrite the legend's entries to be "one 20, two 30, three 10". One way around this is to define the dat$label
as a factor with levels c("one 20", "two 10", "three 30") so the legend is ordered by the factor levels.
To cut a long story short, the code below should solve your problem:
piePlot <- function(count, categories) {
dat <- data.frame(count = count, category = categories)
dat$fraction <- dat$count / sum(dat$count)
dat$ymax <- cumsum(dat$fraction)
dat$ymin <- c(0, head(dat$ymax, n = -1))
dat$label <- factor(paste(dat$category, dat$count), levels = paste(dat$category, dat$count))
plot <-
ggplot(dat, aes(
fill = label, # fill by label not category
ymax = ymax,
ymin = ymin,
xmin = 0,
xmax = 1
)) +
geom_rect() +
coord_polar(theta = "y") +
scale_fill_brewer(guide = "legend") # no need for labels anymore
plot
}
library(ggplot2)
piePlot(count = c(20, 10, 30),
categories = c("one", "two", "three"))
Upvotes: 1