I saw this in a recent economist and I was wondering if anyone has code that would help replicate it using ggplot. Economist Chart
Thanks!
I saw this in a recent economist and I was wondering if anyone has code that would help replicate it using ggplot. Economist Chart
Thanks!
The latticeExtra package has a theme styled after The Economist magazine which should help as a start.
However, that uses lattice whereas all the kids these days clamor for ggplot2 ...
bigmacprice=rnorm(10)
names(bigmacprice)=1:10
par(bg="lightblue")
barplot(sort(bigmacprice),
horiz=T,
legend="Bunfight!! \nBigmac index \nyadda \nyadda \nmmnnnkay ",
args.legend = list( x = "topleft",
bty="n"
),
col='darkblue'
)
I know you asked for ggplot but I have no idea how this worked but wanted to do one for me (my way).
And so, I came upon this:
http://code.google.com/apis/visualization/documentation/reference.html#barformatter
Hope you find it interesting!
Good luck!
Trufa
There's a good overview of creating these charts with ggplot2 on the LearnR blog: http://learnr.wordpress.com/2009/06/01/ggplot2-positioning-of-barplot-category-labels/
I think the best (quickest, easiest) way to achieve precise typesetting of an R graphic is to use basic R functions to produce the main detail (use ggplot with geom_bar in this case, or base graphics barplot) and then save the plot to an SVG file. Open the SVG in your favourite editing package (Inkscape impresses me more every time I use it) and then do the final typesetting there.
You can then do things like grab a legend and move it around, delete elements, add text anywhere with any formatting in any font etc.
I played around a little using only base plot functionality. This is the result:
Here is the code that produced it:
bigmacprice <- data.frame(
country = c("Switzerland", "Brazil", "Euro area",
"Canada", "Japan", "United States",
"Britain", "Singapore", "South Korea",
"South Africa", "Mexico", "Thailand",
"Russia", "Malaysia", "China"),
price = c(6.78, 5.26, 4.79, 4.18, 3.91, 3.71,
3.63, 3.46, 3.03, 2.79, 2.58, 2.44,
2.39, 2.25, 2.18)
)
plotbigmac <- function(mac, base = "United States", xlim = c(-40, 100)) {
mac <- mac[order(mac$price),]
base = which(mac$country == base)
height <- (mac$price / mac[base, "price"] - 1) * 100
par(bg = "#d0e0e7", col.main = "#262324", col.axis = "#393E46",
mar = c(8, 8, 6, 6), las = 1)
barplot(height, width = .1, space = .4,
names.arg = mac$country, #cex.names = .8,
col = "#01516c", border = "#7199a8", # border = "#577784",
horiz = TRUE, xlim = c(-40, 100), axes = FALSE)
axis(3, lty = 0)
title(main = "Bunfight\nBig Mac index", col = "#393E46")
abline(v = seq(-100, 100, 10), col = "white", lwd = 2)
abline(v = 0, col = "#c8454e", lwd = 2)
par(xpd = TRUE)
for (i in 1:nrow(mac)) {
rect(105, (i - 1) / 7, 118, i / 7 - 0.05,
col = "white", border = "#7199a8")
text(112, (i - 1) / 7 + 0.05, mac$price[i], cex = 0.8, col = "#393E46")
}
rect(-120, 2.5, -90, 3, col = "#c8454e", border = "#c8454e")
text(-68, -.2, "Sources:", col = "#393E46")
text(-64, -.3, "McDonald's;", col = "#393E46")
text(-60, -.4, "The Economist", col = "#393E46")
}
plotbigmac(bigmacprice)
It might not be the exact match (ex. i don't know how to right align without calling text directly), and if you try to resize it the text will jump around, so you would have to tweak the parameters further to fit your needs. But it goes to show that you can get far with using only basic plot functionality in R.
EDIT: As was commented, the white stripes cross the bars. This is inevitable and cant be adjusted with another call to barplot
since that would redraw the plot area. Thus we have to take a peek into the source-code of barplot
and customize it for this purpose (love how easy this is in R). But now we have moved outside of the comfy basics in R (i.e. using built in barplot). Here is another go at it:
plotBigMac <- function(mac, base = "United States") {
old.par <- par(no.readonly = TRUE)
on.exit(par(old.par))
# Create data:
mac <- mac[order(mac$price),]
base = which(mac$country == base)
height <- (mac$price / mac[base, "price"] - 1) * 100
# Costume 'barplot'
NN <- length(height)
width <- rep(1, length.out = NN)
delta <- width / 2
w.r <- cumsum(width + 0.5)
w.m <- w.r - delta
w.l <- w.m - delta
xlim <- c(range(-.01 * height, height)[1], 100)
ylim <- c(min(w.l), max(w.r))
par(bg = "#d0e0e7", col.main = "#262324", col.axis = "#393E46",
mar = c(8, 8, 6, 6), las = 1, cex = 0.9)
plot.new()
plot.window(xlim, ylim)
abline(v = seq(-100, 100, 20), col = "white", lwd = 2)
rect(0, w.l, height, w.r, col = "#01516c", border = "#7199a8", lwd = 1)
# Lines and axis
abline(v = 0, col = "#c8454e", lwd = 2)
axis(3, axTicks(3), abs(axTicks(3)), lty = 0)
axis(2, labels = mac$country, at = w.m, lty = 0)
# Move outside of plot area
par(xpd = TRUE)
# Text misc.
text(5, (w.l[base] + w.r[base]) / 2, "nil", font = 3)
text(8, w.r[NN] + 2.3, "+")
text(-8, w.r[NN] + 2.3, "-")
# Create price boxes:
rect(105, w.l, 125, w.r,
col = "white", border = "#7199a8", lwd = 1)
text(115, (w.r + w.l)/2, mac$price, cex = 0.8, col = "#393E46")
}
Which creates this: