# How can I produce a mosaic chart / Marimekko chart?

I would like to make a stacked ybar plot with three stacked components on each bar, with each component divided vertically into three percentage components (the total width of these components stay the same: 100%). One bar of the plot could be described by the following matrix:

23 30% 50% 20%

55 10% 40% 50%

32 60% 30% 10%

meaning that the first (base) part of the bar would have a hight of 32, and be devided into three parts vertically with relative widths 60:30:10 (so three narrow lines with different widths standing next to each other and touching). The second (middle part) would have a hight of 55, added on top of the 32-high first bar, and be divided into three parts with relative widths 10:40:50. The third (top) part would have a height of 23, divided into three parts with relative widths 30:50:20.

(The input format is not important, and flipping around the numbers or dividing the matrix into two or more does not matter---the important part is getting plot as described.)

Does anyone have any suggestions on how to achieve this?

edit: Clarification:

The above example and table describes only one of the bars.

Another way to describe it would be to make a ybar plot, where each ybar is a mosaic chart or a Marimekko chart, so that each bar contains the kind of chart that is presented below in the answer by Jake.

-

This chart type is called a mosaic chart or a Marimekko chart. There's an insightful critique of this type of chart over at Junk Charts that points out some of the shortcomings one has to be aware of.

Nonetheless, they can be created in PGFPlots relatively easily, in your case by combining xbar interval with stack dir=x. xbar interval allows the creation of horizontal bars with different thicknesses according to the y value. In order for this to work, you need to add a dummy data row to your table, and you need to accumulate the y values, otherwise the bars would overlap. You can do that with a create on use expression using pgfplotstable. The xbar interval needs to be supplied to the individual plots, not the axis, since otherwise the different parts of the bars would be offset relatively to each other.

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots, pgfplotstable}

23 30 50 20
55 10 40 50
32 60 30 10
0 0 0 0
}\datatable

\pgfplotstableset{
create on use/accumy/.style={
create col/expr={\prevrow{0}+\pgfmathaccuma}
}
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
stack plots=x,
enlargelimits=false,
table/y=accumy]
\addplot [fill=orange!60,xbar interval] table [x index=1] {\datatable};
\addplot [fill=cyan!50,xbar interval] table [x index=2] {\datatable};
\addplot [fill=yellow!50,xbar interval] table [x index=3] {\datatable};
\end{axis}
\end{tikzpicture}
\end{document}


To create a chart consisting of several such charts, I believe your best bet is to use individual axis environments positioned relatively to each other. It's not possible to have several independent stack plots in one axis environment.

In my opinion, the result is quite pretty to look at, but not very useful for communicating data =).

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots, pgfplotstable}

23 30 50 20
55 10 40 50
32 60 30 10
0 0 0 0
}\datatableA

11 10 50 40
20 30 20 50
60 30 50 20
0 0 0 0
}\datatableB

33 30 50 20
55 10 40 50
32 60 30 10
0 0 0 0
}\datatableC

\pgfplotstableset{
create on use/accumy/.style={
create col/expr={\prevrow{0}+\pgfmathaccuma}
}
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
width=3cm, y=0.03cm,
name=main axis,
hide x axis,
stack plots=x,
enlargelimits=false,
table/y=accumy]
\addplot [fill=orange!60,xbar interval] table [x index=1] {\datatableA};
\addplot [fill=cyan!50,xbar interval] table [x index=2] {\datatableA};
\addplot [fill=yellow!50,xbar interval] table [x index=3] {\datatableA};
\end{axis}

\begin{axis}[
name=second axis,
at=(main axis.south east), anchor=south west, xshift=1ex,
width=3cm, y=0.03cm, hide axis,
stack plots=x,
enlargelimits=false,
table/y=accumy]
\addplot [fill=orange!60,xbar interval] table [x index=1] {\datatableB};
\addplot [fill=cyan!50,xbar interval] table [x index=2] {\datatableB};
\addplot [fill=yellow!50,xbar interval] table [x index=3] {\datatableB};
\end{axis}

\begin{axis}[
at=(second axis.south east), anchor=south west, xshift=1ex,
width=3cm, y=0.03cm, hide axis,
stack plots=x,
enlargelimits=false,
table/y=accumy]
\addplot [fill=orange!60,xbar interval] table [x index=1] {\datatableC};
\addplot [fill=cyan!50,xbar interval] table [x index=2] {\datatableC};
\addplot [fill=yellow!50,xbar interval] table [x index=3] {\datatableC};
\end{axis}
\end{tikzpicture}
\end{document}

-
I appreciate your informative answer, as well as the caution not to make charts to complicated (or ugly ;)). I realize that I did not state my question in the clearest way---the plot that you described in your answer should be just one of the bars in the plot I want. In other words, take the plot in the answer, squeeze it from the sides so that it becomes tall and narrow, and then add more such bars. I realize that there is a substantial risk that it may be to cramped to be useful, but I would still like to try it out if it is possible. –  hjb981 Jul 10 '12 at 9:29
@hjb981: Wow, hehe, that's going to be messy. I've edited my answer to show one possible way of doing that. –  Jake Jul 10 '12 at 9:47
Wow, impressively fast! I just drew a picture of the above and went to the scanner, and when I was back to my computer to upload it, there was your answer. And yes, I agree, it may be way to messy, but I still really appreciate your answer so that I now have the option of trying, to see what it will look like. –  hjb981 Jul 10 '12 at 10:02
Marimekko chart? Seriously? :-D –  morbusg Jul 10 '12 at 11:07
@Jake If you try the examples with pgfplots version 1.10 or 1.11, the output is different (and wrong). –  egreg Oct 10 '14 at 9:21