Bull charts
A colleague of mine needs to sketch 101 bull's eyes. This is not her idea. Instead of having a slave in Excel, or God knows what it does, I suggested making them in R; mapping the line plot to polar coordinates to make bulls-eyes is wind at ggplot2
.
I ran into a problem, however: the data is already aggregated, so Hadley's example here doesn't work for me. I could expand the abacus into factor to do this, but I feel like there is a better way - somehow tell geom_bar how to read the data.
The data looks like this:
Zoo Animals Bears Polar Bears
1 Omaha 50 10 3
I will make a plot for each zoo, but this part I can handle.
and here it is 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 important that animals> = bears> = polar bears. Also, she's leaving town, so I can't just get the raw data from her (if there was a large file anyway).
source to share
The way to do this without disaggregating is to use stat="identity"
in geom_bar
.
This helps to create a data frame containing numeric values, not character strings:
dat <- data.frame(Zoo = "Omaha",
Animals = 50, Bears = 10, `Polar Bears` = 3)
We need reshape2::melt
to set up the data correctly:
library(reshape2)
d3 <- melt(dat,id.var=1)
Now create a 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()
source to share
While 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()
source to share
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))
source to share