How can I do plot a waffle chart as an alternative to using piecharts in R?
help.search("waffle")
No help files found with alias or concept or title matching ‘waffle’
using fuzzy matching.
The closest I found googling out there are mosaicplots.
Cross Validated is a question and answer site for people interested in statistics, machine learning, data analysis, data mining, and data visualization. It only takes a minute to sign up.
Sign up to join this communityHow can I do plot a waffle chart as an alternative to using piecharts in R?
help.search("waffle")
No help files found with alias or concept or title matching ‘waffle’
using fuzzy matching.
The closest I found googling out there are mosaicplots.
Now there is a package called waffle.
Example from the github page:
parts <- c(80, 30, 20, 10)
waffle(parts, rows=8)
Result:
Regards
I suspect that geom_tile
from the package ggplot2
can do what you're looking for. Shane's answer on this StackOverflow question should get you started.
Edit: Here's an example, with a few other plots for comparison.
library(ggplot2)
# Here's some data I had lying around
tb <- structure(list(region = c("Africa", "Asia", "Latin America",
"Other", "US-born"), ncases = c(36L, 34L, 56L, 2L, 44L)), .Names = c("region",
"ncases"), row.names = c(NA, -5L), class = "data.frame")
# A bar chart of counts
ggplot(tb, aes(x = region, weight = ncases, fill = region)) +
geom_bar()
# Pie chart. Forgive me, Hadley, for I must sin.
ggplot(tb, aes(x = factor(1), weight = ncases, fill = region)) +
geom_bar(width = 1) +
coord_polar(theta = "y") +
labs(x = "", y = "")
# Percentage pie.
ggplot(tb, aes(x = factor(1), weight = ncases/sum(ncases), fill = region)) +
geom_bar() +
scale_y_continuous(formatter = 'percent') +
coord_polar(theta = "y") +
labs(x = "", y = "")
# Waffles
# How many rows do you want the y axis to have?
ndeep <- 5
# I need to convert my data into a data.frame with uniquely-specified x
# and y coordinates for each case
# Note - it's actually important to specify y first for a
# horizontally-accumulating waffle
# One y for each row; then divide the total number of cases by the number of
# rows and round up to get the appropriate number of x increments
tb4waffles <- expand.grid(y = 1:ndeep,
x = seq_len(ceiling(sum(tb$ncases) / ndeep)))
# Expand the counts into a full vector of region labels - i.e., de-aggregate
regionvec <- rep(tb$region, tb$ncases)
# Depending on the value of ndeep, there might be more spots on the x-y grid
# than there are cases - so fill those with NA
tb4waffles$region <- c(regionvec, rep(NA, nrow(tb4waffles) - length(regionvec)))
# Plot it
ggplot(tb4waffles, aes(x = x, y = y, fill = region)) +
geom_tile(color = "white") + # The color of the lines between tiles
scale_fill_manual("Region of Birth",
values = RColorBrewer::brewer.pal(5, "Dark2")) +
opts(title = "TB Cases by Region of Birth")
Clearly, there's extra work to be done on getting the aesthetics right (e.g., what the hell do those axes even mean?), but that's the mechanics of it. I leave "pretty" as an exercise for the reader.
Here's one in base r using @jbkunst 's data:
waffle <- function(x, rows, cols = seq_along(x), ...) {
xx <- rep(cols, times = x)
lx <- length(xx)
m <- matrix(nrow = rows, ncol = (lx %/% rows) + (lx %% rows != 0))
m[1:length(xx)] <- xx
op <- par(no.readonly = TRUE)
on.exit(par(op))
par(list(...))
plot.new()
o <- cbind(c(row(m)), c(col(m))) + 1
plot.window(xlim = c(0, max(o[, 2]) + 1), ylim = c(0, max(o[, 1]) + 1),
asp = 1, xaxs = 'i', yaxs = 'i')
rect(o[, 2], o[, 1], o[, 2] + .85, o[, 1] + .85, col = c(m), border = NA)
invisible(list(m = m, o = o))
}
cols <- c("#F8766D", "#7CAE00", "#00BFC4", "#C77CFF")
m <- waffle(c(80, 30, 20, 10), rows = 8, cols = cols, mar = c(0,0,0,7),
bg = 'cornsilk')
legend('right', legend = LETTERS[1:4], pch = 15, col = cols, pt.cex = 2,
bty = 'n')