Question

A colleague of mine needs to plot 101 bull's-eye charts. This is not her idea. Rather than have her slave away in Excel or God knows what making these things, I offered to do them in R; mapping a bar plot to polar coordinates to make a bull's-eye is a breeze in ggplot2.

I'm running into a problem, however: the data is already aggregated, so Hadley's example here isn't working for me. I could expand the counts out into a factor to do this, but I feel like there's a better way - some way to tell the geom_bar how to read the data.

The data looks like this:

    Zoo Animals Bears Polar Bears
1 Omaha      50    10           3

I'll be making a plot for each zoo - but that part I can manage.

and here's its dput:

structure(list(Zoo = "Omaha", Animals = "50", Bears = "10", `Polar Bears` = "3"), .Names = c("Zoo", 
"Animals", "Bears", "Polar Bears"), row.names = c(NA, -1L), class = "data.frame")

Note: it is significant that Animals >= Bears >= Polar Bears. Also, she's out of town, so I can't just get the raw data from her (if there was ever a big file, anyway).

Was it helpful?

Solution

The way to do this without disaggregating is to use stat="identity" in geom_bar.

It helps to have the data frame containing numeric values rather than character strings to start:

dat <- data.frame(Zoo = "Omaha",
               Animals = 50, Bears = 10, `Polar Bears` = 3)

We do need reshape2::melt to get the data organized properly:

library(reshape2)
d3 <- melt(dat,id.var=1)

Now create the plot (identical to the other answer):

library(ggplot2)
ggplot(d3, aes(x = variable, y = value)) +
    geom_bar(width = 1, colour = "black",stat="identity") +
    coord_polar()

OTHER TIPS

While we're waiting for a better answer, I figured I should post the (suboptimal) solution you mentioned. dat is the structure included in your question.

d <- data.frame(animal=factor(sapply(list(dat[2:length(dat)]),
                function(x) rep(names(x),x))))
cxc <- ggplot(d, aes(x = animal)) +  geom_bar(width = 1, colour = "black") 
cxc + coord_polar() 

You can use inverse.rle to recreate the data,

dd = list(lengths = unlist(dat[-1]), values = names(dat)[-1])
class(dd) = "rle"
inverse.rle(dd)

If you have multiple Zoos (rows), you can try

l = plyr::dlply(dat, "Zoo", function(z)  
      structure(list(lengths = unlist(z[-1]), values = names(z)[-1]), class = "rle"))

reshape2::melt(llply(l, inverse.rle))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top