Skip to content

ggplot2: Marimekko Replacement – Overlapping Bars

April 2, 2009

Jon Peltier’s tutorial demonstrates an alternative to the Marimekko chart.

https://learnr.files.wordpress.com/2009/04/mekkobarchart08.png

While reproducing the two individual graphs in ggplot2 goes smoothly, the final formatting is a bit trickier.



Data Preparation

As always, before plotting the data needs to be prepared first.

Create dataframe

> df <- read.csv(textConnection("
+ Segment,Alpha,Beta,Gamma,Delta
+ A,1416649,590270,236108,118054
+ B,708325,531243,354162,177081
+ C,354162,354162,236108,236108
+ D,147568,147568,147568,147568"))
> closeAllConnections()

Convert data to long format

> library(reshape)
> dfa <- melt(df, id = c("Segment"), variable_name = "Company")

Determine maximum y-axis values to later set the axis limits

> ylim <- max(cast(dfa, Company ~ ., sum)[, 2],
+     cast(dfa, Segment ~ ., sum)[, 2])

Plotting Using Default formatting

Plotting data from different angles: by company and by segment is straightforward.

Plotting using Default formatting

> library(ggplot2)
> p <- ggplot(dfa) + scale_y_continuous(limits = c(0,
+     ylim), breaks = NA)
> p1 <- p + geom_bar(aes(Company, value), stat = "identity")
> p2 <- p1 + geom_bar(aes(Company, value, fill = Segment),
+     stat = "identity", position = "dodge")
https://learnr.files.wordpress.com/2009/04/marimekko2-p21.png
> p3 <- p + geom_bar(aes(Segment, value), stat = "identity")
> p4 <- p3 + geom_bar(aes(Segment, value, fill = Company),
+     stat = "identity", position = "dodge")
marimekko2-p4

Plot Layout Setup

Now we need to position the two plots above side-by-side. I will be using a small trick to do this – there will be actually three plots combined into one. The reason for this is that the first plot (1.1) will be purely used for the axis labels, as plots 2&3 (1.2 & 1.3) will have their y-labels removed. It should be noted that the width of the first plot (currently 4 lines) needs to be manually tweaked to produce the best results.

Plot Layout Setup

> Layout <- grid.layout(nrow = 1, ncol = 3, widths = unit(c(4,
+     2, 2), c("lines", "null", "null")), heights = unit(c(1,
+     1, 1), c("null", "null", "null")))
> grid.show.layout(Layout)
marimekko2-layout

Convenience Functions

I also set up a few helper functions that will be used later to set up the grid, and format axis labels:

> vplayout <- function(...) {
+     grid.newpage()
+     pushViewport(viewport(layout = Layout))
+ }
> subplot <- function(x, y) viewport(layout.pos.row = x,
+     layout.pos.col = y)

Full Plot function

> mmplot <- function(a, b, c) {
+     vplayout()
+     print(a, vp = subplot(1, 1:2))
+     print(b, vp = subplot(1, 2))
+     print(c, vp = subplot(1, 3))
+ }

Number formatting function

> formatter <- function(x, prefix = "$") {
+     ifelse(x > 999999999, paste(prefix, comma(x/1e+09,
+         nsmall = 1), "bn", sep = ""), ifelse(x >
+         999999, paste(prefix, comma(x/1e+06),
+         "m", sep = ""), ifelse(x > 999, paste(prefix,
+         comma(x/1000), "k", sep = ""), paste(prefix,
+         comma(x), sep = ""))))
+ }

Draft Plot

After drawing the plot with only y-axis values, we are finally ready to see what the combined plot looks like.

> px <- p + geom_blank(aes(0.1, value)) + scale_y_continuous(limits = c(0,
+     ylim))
> mmplot(px, p2, p4)
marimekko2-1

Final Plot

A few changes need to be made to this plot: adjust the position of legends, change default colour scheme, format and/or delete the y-axes labels of individual plots.

Position legends, adjust background so that all three plots blend in

> pa <- ggplot(dfa) + scale_y_continuous(limits = c(0,
+     ylim), breaks = NA) + opts(legend.position = c(0.8,
+     0.85), legend.background = theme_rect(colour = NA)) +
+     opts(panel.background = theme_rect(fill = "white",
+         colour = NA)) + opts(panel.grid.minor = theme_blank(),
+     panel.grid.major = theme_blank())
> pxa <- pa + geom_blank(aes(0.1, value)) + scale_y_continuous(formatter = formatter,
+     limits = c(0, ylim))

Plot by Company

> p1a <- pa + geom_bar(aes(Company, value), stat = "identity",
+     fill = "dodgerblue4")
> p1a <- p1a + opts(plot.margin = unit(c(1, 0, 0.5,
+     -1), "lines"))
> p2a <- p1a + geom_bar(aes(Company, value, fill = Segment),
+     stat = "identity", position = "dodge")
> p2a <- p2a + scale_fill_brewer(palette = "Blues")

Plot by Segment

> p3a <- pa + geom_bar(aes(Segment, value), stat = "identity",
+     fill = "mediumseagreen")
> p3a <- p3a + opts(plot.margin = unit(c(1, 1, 0.5,
+     -0.5), "lines"))
> p4a <- p3a + geom_bar(aes(Segment, value, fill = Company),
+     stat = "identity", position = "dodge")
> p4a <- p4a + scale_fill_brewer(palette = "Greens")
> mmplot(pxa, p2a, p4a)
marimekko2-2
6 Comments leave one →
  1. September 17, 2009 5:20 pm

    Compared to lattice I find ggplot2 to be too cumbersome and cluttered. In lattice it is so easy to easy to place multiple plots on same sheet with mfrow setting. I have wasted considerable time in ggplot2 trying to do the same

    • learnr permalink*
      September 17, 2009 5:58 pm

      I don’t think you can use par(mfrow…) settings with lattice.

      From ?Lattice:
      “Lattice plots are highly customizable via user-modifiable settings. However, these are completely unrelated to base graphics settings; in particular, changing par() settings usually have no effect on lattice plots.”

      gridextra package includes a convenience function arrange to easily organise ggplo2 plots on a page. Have a look!

  2. John Thompson permalink
    March 4, 2011 9:41 am

    In trying to replicate this example plot (which I really like) I am getting an ERROR on the
    ‘mmplot…’ line.

    “Error in +grid.newpage() : invalid argument to unary operator”

    Do you have any idea how I should address this error?

    Thanks,
    John

  3. John Thompson permalink
    March 4, 2011 8:37 pm

    Hello,

    I really like this plot, but I am having trouble replicating your code. The error message I keep getting occurs when I run the final mmplot code :

    Error: unexpected symbol in “vplayout <- function(…) {grid.newpage() pushViewport"

  4. John Thompson permalink
    March 4, 2011 8:47 pm

    Also this error with mmplot: “Error in +vplayout() : invalid argument to unary operator”

Trackbacks

  1. ggplot2: Marimekko Replacement - 2 by 2 Panel « Learning R

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: