[Tex/LaTex] pgfplot/tikz stacked bar chart

bar charttikz-pgf

I have the following table with data

enter image description here

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

enter image description here

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:

enter image description here

and the chart:

enter image description here

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

enter image description here

Best Answer

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.

enter image description here

\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}