2

I need to plot three pie charts using the following data frame:

df <- data.frame(id = rep(LETTERS[1:3], each=5),
                 var = rep(letters[1:5], 3),
                 value = c(10, 8, 6, 4, 2))

This code produce the type of chart I want:

library(ggplot2)
ggplot(df, aes(x = factor(1), fill = var, weight=value)) +
    geom_bar(width = 1.2, colour = "white") +
    coord_polar(theta="y") +
    facet_wrap( ~ id)

enter image description here

The problem arise when I need to add some text to label each slice of the pie:

ggplot(df, aes(x = factor(1), fill = var, weight=value)) +
    geom_bar(width = 1.2, colour = "white") +
    coord_polar(theta="y") +
    geom_text(aes(x = 1.8, y=rowMeans(embed(c(0,cumsum(value)),2)),
                  label=sprintf("%.1f", value)), size = 5, colour = "grey25") +
    facet_wrap( ~ id)

enter image description here

It seems that rowMeans(embed(c(0,cumsum(value)),2)) is not evaluated against the portion of data being displayed by each facet (as I would expect).

Having created a very trivial case, the positions should be always the same:

> rowMeans(embed(c(0,cumsum(df$value[ df$id == "A"])),2))
[1]  5 14 21 26 29
> rowMeans(embed(c(0,cumsum(df$value[ df$id == "B"])),2))
[1]  5 14 21 26 29
> rowMeans(embed(c(0,cumsum(df$value[ df$id == "C"])),2))
[1]  5 14 21 26 29

Q: What is actually ggplot doing when evaluating the above expression?

Jaap
  • 81,064
  • 34
  • 182
  • 193
Michele
  • 8,563
  • 6
  • 45
  • 72
  • 1
    I can't answer what exactly `ggplot` does, but in case you haven't tried this, first calculating the y's (storing them in a new column of df) and then calling ggplot referencing that column (instead of the formula) works. Eg `df <- ddply(df, .(id), transform, v = rowMeans(embed(c(0,cumsum(value)),2)))` and then using the same statement you have with `y=v` in `geom_text`. – konvas Jun 23 '14 at 13:00
  • @Michelle Didn't my anwer work? I was just wondering because you didn't accept it. If it didn't, I like to know what was wrong, so I can improve on it. – Jaap Nov 25 '14 at 19:42
  • @Jaap It worked indeed! I really don't know why I didn't vote nor accept it months ago. Sorry about that. – Michele Nov 26 '14 at 15:01

1 Answers1

7

It's better to achieve the desired result by creating a position variable (as I also showed in this answer). Applying this method to your situation:

# creating the position variable
library(dplyr)
df <- df %>%
  group_by(id) %>%
  mutate(pos=cumsum(value) - 0.5*value)

# creating the plot
ggplot(df, aes(x = factor(1), fill = var, weight=value)) +
  geom_bar(width = 1.2, colour = "white") +
  coord_polar(theta="y") +
  geom_text(aes(x = 1.8, y=pos, label=sprintf("%.1f", value)), size = 5, colour = "grey25") +
  facet_wrap( ~ id)

which gives: enter image description here

Community
  • 1
  • 1
Jaap
  • 81,064
  • 34
  • 182
  • 193