# pgfplot/tikz stacked bar chart

I have the following table with data

And I am trying to replicate it in a stacked bar chart. Could anybody help to build this kind of chart?

The table is easy to replicate it in latex, but I am having problems with the chart as there are two kind of data to be showed: 1) the overall (which is the dark blue and thin bar and 2) the stacked sub-index. Another problem is because there are no x or y-axis and the value of the overall index is showed besides the stacked bars. I am really puzzled if it is possible to replicate all of this in latex. The headings and titles are not important, just the chart and legend showing the colors and definition that is what counts for me.

Thanks for your time and invaluable help guys!

After some answers and little modifications this is what I have:

and the chart:

Unable to show the legend properly nor removing the vertical bars between the stacked bars

• I honestly don't see the point of the "overall" bar. There are several examples of stacked bar charts on the site, How to draw bar chart using tikz? should get you on the way. How can I get a stacked bar with single values and sum on top. shows a way of getting the sum on top. – Torbjørn T. Jul 26 '16 at 8:55
• The overall index is the result of multiplying the Adequacy, Sustainability and Integrity by 40%, 35% and 25% and sum them up. I.e.: for Australia you get: 81,2*0.4+72,1*0.35+87,6*0.25 = 79,6 for that reason is also important to show the bar. I tried to check the examples but they are all based on x-axis. – José Jul 26 '16 at 11:12

## 2 Answers

Using Jake's answer to How to draw bar chart using tikz? as a starting point, and adding a bit from Robert's answer to get the number at the end of the bars, and with a few modifications here and there. Also added an example of typesetting the table based on the same \pgfplotstable.

The values are calculated based on the table you showed and the coefficients you mentioned in the comment, see the x expr statements in the \addplot options.

There are a few comments in the code, ask if anything looks like black magic.

Update: I thought of an easy way of doing the bar for the total in addition. I basically made a new axis of the same size, plotted the total there as an xcomb plot (an xbar would probably also work), and then I shifted the whole axis down a bit with yshift. I also moved the ticklabels and the numbers down a bit.

\documentclass{article}
\usepackage{pgfplots, pgfplotstable,booktabs}
\usetikzlibrary{positioning}

\pgfplotstableread{ % Read the data into a table macro
Country Total Adequacy Sustainability Integrity
Australia 79.6 81.2 72.1 87.6
China 48.0 62.7 29.8 50.0
Netherlands 80.5 80.5 74.3 89.3
Australia 79.6 81.2 72.1 87.6
China 48.0 62.7 29.8 50.0
Netherlands 80.5 80.5 74.3 89.3
Australia 79.6 81.2 72.1 87.6
China 48.0 62.7 29.8 50.0
Netherlands 80.5 80.5 74.3 89.3
Australia 79.6 81.2 72.1 87.6
China 48.0 62.7 29.8 50.0
Netherlands 80.5 80.5 74.3 89.3
Australia 79.6 81.2 72.1 87.6
China 48.0 62.7 29.8 50.0
Netherlands 80.5 80.5 74.3 89.3
Australia 79.6 81.2 72.1 87.6
China 48.0 62.7 29.8 50.0
Netherlands 80.5 80.5 74.3 89.3
Australia 79.6 81.2 72.1 87.6
China 48.0 62.7 29.8 50.0
Netherlands 80.5 80.5 74.3 89.3
Australia 79.6 81.2 72.1 87.6
China 48.0 62.7 29.8 50.0
Netherlands 80.5 80.5 74.3 89.3
Australia 79.6 81.2 72.1 87.6
China 48.0 62.7 29.8 50.0
Netherlands 80.5 80.5 74.3 89.3
Australia 79.6 81.2 72.1 87.6
China 48.0 62.7 29.8 50.0
Netherlands 80.5 80.5 74.3 89.3
}\datatableunsort

% sort table by total score, save in new macro
\pgfplotstablesort[sort key={Total}]\datatable\datatableunsort

% define some colours
\definecolor{adequate}{RGB}{37,165,203}
\definecolor{sustainable}{RGB}{253,177,26}
\definecolor{integral}{RGB}{175,32,67}
\definecolor{total}{RGB}{0,69,122}

% define a macro for easier generation of the list of #1s above the legend
\newcommand\numberones[5][a]{%
\begin{scope}[#3,every node/.style={font=\sffamily},inner sep=1pt]
\node [above=5pt of #2,anchor=south west] (#1-1) {#5};
\node [above=0pt of #1-1.north west,anchor=south west,font=\bfseries\sffamily] (#1-2) {#4};
\node [left=0pt of #1-1.south west,anchor=south east,scale=2] (#1-3) {1};
\node [left=0pt of #1-3.north west,anchor=north east] (#1-4) {\#};
\end{scope}}

\begin{document}

\section{Typeset a table}

\pgfplotstabletypeset[
fixed,fixed zerofill,precision=1,
columns/Country/.style={column type=l,string type},
every head row/.style={
before row={
\toprule
&&\multicolumn{3}{c}{Sub-index values} \\ \cmidrule{3-5}},
after row={\midrule}},
every last row/.style={after row=\bottomrule},
]{\datatableunsort}

\section{Bar chart}

\begin{tikzpicture}
\begin{axis}[
% modify the height and width of the axis
height=18cm,width=10cm,
title={2015 \textbf{RESULTS}}, % set title, placed above axis
every axis title/.append style={font=\Huge\sffamily,color=black!60}, % modify look of title
xbar stacked,   % Stacked horizontal bars
bar width=7pt, % for xbar, height of the bars
enlargelimits={abs=4pt}, % a bit more than half the bar width
axis line style={draw=none}, % don't draw the axis lines
axis x line=none, % remove ticks and tick labels from x axis
ytick style={draw=none}, % don't draw ticks on y-axis (but leave ticklabels)
xmin=0,         % Start x axis at 0
ytick=data,     % Use as many tick labels as y coordinates
yticklabels from table={\datatable}{Country},  % use the Country column in the table for ticklabels
y tick label style={yshift=-2pt,black!70,font=\sffamily}, % set ticklabels in dark gray, sans serif
legend style={ % define legend style
row sep=3pt, % increase spacing a bit
name=ThaLegend, % used to position the #1s
draw=none, % don't draw frame
at={(1,0)}, % legend position: places the anchor in the bottom right corner of the axis
anchor=south west, % sets the anchor of the legend to the bottom left
cells={anchor=west,font=\sffamily}}, % left align legend text, change font
legend image code/.code={% defines how the legend is drawn
\fill[#1] (0cm,-0.1cm) rectangle (0.28cm,0.18cm);
}
]

% we don't plot the total here, but add a legend entry
\addlegendimage{fill=total}

% plot values for adequacy,
\addplot [fill=adequate,draw=none] table[x expr=\thisrow{Adequacy}*0.4, y expr=\coordindex] {\datatable};

% sustainability,
\addplot [fill=sustainable,draw=none] table [x expr=\thisrow{Sustainability}*0.35, y expr=\coordindex] {\datatable};

% and integrity
\addplot [fill=integral,draw=none,
% the following places the total to the right of the bards
point meta=x,
nodes near coords={\pgfmathprintnumber[assume math mode=true]{\pgfplotspointmeta}},
nodes near coords align={anchor=west},
every node near coord/.append style={
yshift=-2pt,
font=\sffamily\bfseries\footnotesize, % change font style
color=total % set colour of numbers, total is a colour defined above
}] table [x expr=\thisrow{Integrity}*0.25, y expr=\coordindex] {\datatable};

% add legend
\legend{TOTAL,ADEQUACY,SUSTAINABILITY,INTEGRITY}
\end{axis}

% new axis for the total bar
\begin{axis}[yshift=-6pt,% move down a bit
% modify the height and width of the axis, same as above
height=18cm,width=10cm,
enlargelimits={abs=4pt}, % same as aboe
axis lines=none, % remove axis
xmin=0,         % Start x axis at 0
]

\addplot [total,line width=3pt,xcomb] table[x=Total,y expr=\coordindex] {\datatable};

\end{axis}

% helper path to define a coordinate
\path (ThaLegend.north) -- (ThaLegend.north west) coordinate[pos=0.5](A);
% add the four #1s
\numberones[i]{A}{integral}{INTEGRITY}{FINLAND}
\numberones[s]{i-2.north west}{sustainable}{SUSTAINABILITY}{DENMARK}
\numberones[a]{s-2.north west}{adequate}{ADEQUACY}{AUSTRALIA}
\numberones{a-2.north west}{total}{TOTAL}{DENMARK}

\end{tikzpicture}

\end{document}

• Ok. Perfect but for any strange reason I am not able to reproduce the legend (the little colored squares don't show), moreover given that the list is bigger I had to modify the coordinates and parameters. In any case fits quite well but the legend. I have posted the new chart above, so you can check it out. The code is basically the same except minor modifications. – José Jul 26 '16 at 16:19
• @José Well, I couldn't be bothered to write down the whole table, had you provided it as plain text I could have tested with everything. I cannot say why the legend doesn't appear though. If you try the exact code above, does the legend not appear? Which version of pgfplots do you have (add \listfiles before \documentclass and look it in the .log file to find out, if you don't know)? – Torbjørn T. Jul 26 '16 at 16:49
• @José Ah, didn't see your screenshot before my previous comment. Still can't say for sure what causes that, but try the updated code in my answer. – Torbjørn T. Jul 26 '16 at 17:36
• !!!! Works perfectly!!!! But I still have the same problem with the lines. See the chart above. I can live with the line on the left between the countries and bars, but the other one which crosses the numbers and legend is pissing me off. The code is exactly the same but for any strange reason and the time to compile it, they appear :( – José Jul 27 '16 at 15:36
• @José Try with axis line style={opacity=0}, instead of axis line style={draw=none},. – Torbjørn T. Jul 27 '16 at 16:14

Try that:

\documentclass{article}
\usepackage{tikz,pgfplots,pgfplotstable}

\begin{document}

\pgfplotstableread{ % data
Label     Adequacy Sustainability Integrity
Austria   21.87797  5.566584 24.85545
Brazil    20.93009  7.937881 24.33203
Chile     20.41148 21.126529 27.56199
Australia 26.83072 23.823827 28.94545
}\testdata

\begin{tikzpicture}

\begin{axis}[
xbar stacked,   % Stacked horizontal bars
xmin=0,         % Start x axis at 0
ytick=data,     % Use as many tick labels as y coordinates
legend style={at={(axis cs:65,0.2)},anchor=south west},
yticklabels from table={\testdata}{Label}  % Get the labels from the Label column of the \datatable
]
\addplot [fill=green!80] table [x=Adequacy, meta=Label,y expr=\coordindex] {\testdata};   % "First" column against the data index
\addplot [fill=blue!60] table [x=Sustainability, meta=Label,y expr=\coordindex] {\testdata};
\addplot [fill=red!60,
point meta=x,
nodes near coords,
nodes near coords align={anchor=west},
every node near coord/.append style={
black,
fill=white,
fill opacity=0.75,
text opacity=1,
outer sep=\pgflinewidth % so the label fill doesn't overlap the plot
}
] table [x=Integrity, meta=Label,y expr=\coordindex] {\testdata};
\legend{Adequacy,Sustainability,Integrity}

\end{axis}
\end{tikzpicture}
\end{document}