Wondering how to output a chart I saw in the economist magazine

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!

Answers


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:


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 ...


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.


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'
)

Need Your Help

"No Such Table" Error found in SQLite Android

java android sqlite

I am trying to learn about SQLite databases, but I really hate dealing with any back-end stuff, with a passion. I'm already hitting walls with a seemingly simple problem.

How to export a SQL Server 2008 Database Diagram to another DB?

sql-server diagram

I use the handy Database Diagramming tool in SQL Server 2008 for creating and managing relationships. I have exported the sourceDB to the destinationDB but the diagram doesn't come across.