3

I am trying to make a barplot, but fill according to the Type of the sample. Here is my MWE:

Currently, this displays all the bars with red. I want the Animal samples in red and the Plant samples in Green.

I have seen other examples where they use "meta" as some group indicator, but those appear to only work for scatter plots.

\documentclass{beamer} \usepackage{pgfplots} \pgfplotsset{compat=1.17} \usepackage{pgfplotstable} \begin{document} \begin{frame} \pgfplotstableread[row sep=\\,col sep=&]{ Source & Emission & Type\\ Meat & 51.1 & Animal\\ Eggs & 32.3 & Animal\\ Vegetable & 19.1 & Plant\\ Legumes & 24.3 & Plant\\ Milk & 18.5 & Animal\\ Cereals & 14.3 & Plant\\ }\proteintable \begin{tikzpicture} \begin{axis}[ xbar, width = 5cm, symbolic y coords={% Meat,% Eggs,% Vegetable,% Legumes,% Milk,% Cereals% }, ytick=data, xmin=0, xlabel={Protein calories (\%)}, legend style={at={(0.8,0.85)}, anchor=center, legend columns=2, draw=none}, xmajorgrids=true, xminorgrids=true, grid style=dashed, label style = {font=\scriptsize}, yticklabel style={xshift=0.6ex, text width=1.7cm, font=\scriptsize, align=right}, ticklabel style = {font=\scriptsize}, ] \addplot [fill=red!60, draw=red] table[y=Source,x=Emission]{\proteintable}; \end{axis} \end{tikzpicture} \end{frame} \end{document} 
4
  • Welcome to TeX.SX! Your question seems to be similar to this one: tex.stackexchange.com/q/37568/47927 Commented May 2 at 15:31
  • Hello @JasperHabicht, thanks for the suggestion, but I'm not sure if can cleanly translate the solution in the suggested link to my problem without restructuring the original datatable. Commented May 2 at 15:45
  • Hello, I have opened a fresh question as the suggested link did not solve my problem. Commented May 3 at 10:07
  • I tried something which is working more or less, but for some reason the bars are not filled. I don’t have the time to look into this today. Maybe I can come up with a solution tomorrow. Commented May 3 at 11:05

1 Answer 1

2

You can make use of this answer, but you need to adjust the code a bit to get the axis labels right. Note that you need to use \addplot+ in order to have the different colors selected automatically.

\documentclass{beamer} \usepackage{pgfplots, pgfplotstable} \pgfplotsset{compat=1.18} \begin{document} \begin{frame} \pgfplotstableread[row sep=\\,col sep=&]{ Source & Emission & Type\\ Meat & 51.1 & Animal\\ Eggs & 32.3 & Animal\\ Vegetable & 19.1 & Plant\\ Legumes & 24.3 & Plant\\ Milk & 18.5 & Animal\\ Cereals & 14.3 & Plant\\ }\proteintable \begin{tikzpicture} \begin{axis}[ xbar, width=5cm, symbolic y coords={% Meat,% Eggs,% Vegetable,% Legumes,% Milk,% Cereals% }, ytick={% Meat,% Eggs,% Vegetable,% Legumes,% Milk,% Cereals% }, xmin=0, xlabel={Protein calories (\%)}, legend style={at={(0.8,0.85)}, anchor=center, legend columns=2, draw=none}, xmajorgrids=true, xminorgrids=true, grid style=dashed, label style={font=\scriptsize}, yticklabel style={xshift=0.6ex, text width=1.7cm, font=\scriptsize, align=right}, ticklabel style={font=\scriptsize}, bar shift=0pt, ] \foreach \i in {0,...,5} { \addplot+[x filter/.expression={\coordindex==\i ? x : nan}] table[y=Source, x=Emission] {\proteintable}; } \end{axis} \end{tikzpicture} \end{frame} \end{document} 

output of above code


To colorize the bars according to the value in the Type column, some trickery is needed to get the expansion in the right order:

\documentclass{beamer} \usepackage{pgfplots, pgfplotstable} \pgfplotsset{compat=1.18} \colorlet{Animal}{red} \colorlet{Plant}{green} \begin{document} \begin{frame} \pgfplotstableread[row sep=\\,col sep=&]{ Source & Emission & Type\\ Meat & 51.1 & Animal\\ Eggs & 32.3 & Animal\\ Vegetable & 19.1 & Plant\\ Legumes & 24.3 & Plant\\ Milk & 18.5 & Animal\\ Cereals & 14.3 & Plant\\ }\proteintable \begin{tikzpicture} \begin{axis}[ xbar, width=5cm, symbolic y coords={% Meat,% Eggs,% Vegetable,% Legumes,% Milk,% Cereals% }, ytick={% Meat,% Eggs,% Vegetable,% Legumes,% Milk,% Cereals% }, xmin=0, xlabel={Protein calories (\%)}, legend style={at={(0.8,0.85)}, anchor=center, legend columns=2, draw=none}, xmajorgrids=true, xminorgrids=true, grid style=dashed, label style={font=\scriptsize}, yticklabel style={xshift=0.6ex, text width=1.7cm, font=\scriptsize, align=right}, ticklabel style={font=\scriptsize}, bar shift=0pt, ] \foreach \i in {0,...,5} { \pgfplotstablegetelem{\i}{Type}\of{\proteintable} \edef\temp{ \noexpand\addplot+[draw=\pgfplotsretval, fill=\pgfplotsretval!50, x filter/.expression={\noexpand\coordindex==\noexpand\i ? x : nan}] table[y=Source, x=Emission] {\noexpand\proteintable}; } \temp } \end{axis} \end{tikzpicture} \end{frame} \end{document} 

output of above code


Actually, I would probably so this with TikZ directly anyways, as it would be much easier to customize everything:

\documentclass{beamer} \usepackage{pgfplotstable} \pgfplotsset{compat=1.18} \colorlet{Animal}{red} \colorlet{Plant}{green} \begin{document} \begin{frame} \pgfplotstableread[row sep=\\,col sep=&]{ Source & Emission & Type\\ Meat & 51.1 & Animal\\ Eggs & 32.3 & Animal\\ Vegetable & 19.1 & Plant\\ Legumes & 24.3 & Plant\\ Milk & 18.5 & Animal\\ Cereals & 14.3 & Plant\\ }\proteintable \pgfplotstablegetrowsof{\proteintable} \pgfmathtruncatemacro\mydatarowcount{\pgfplotsretval-1} \begin{tikzpicture}[scale=0.1] \foreach \row in {0,...,\mydatarowcount} { \pgfplotstablegetelem{\row}{Source}\of{\proteintable} \node[left] at (0,{\row*10+5}) {\pgfplotsretval}; \pgfplotstablegetelem{\row}{Type}\of{\proteintable} \colorlet{barcolor}{\pgfplotsretval} \pgfplotstablegetelem{\row}{Emission}\of{\proteintable} \filldraw[barcolor, fill opacity=0.5] (0,{\row*10+1}) rectangle +(\pgfplotsretval,8); } \draw (0,{(\mydatarowcount+1)*10}) |- (60,0) node[pos=0.75, below=20pt] {Protein calories (\%)}; \foreach \tick in {0,10,...,60} { \draw (\tick,0) -- +(0,5pt) node[pos=0, below] {\tick}; } \end{tikzpicture} \end{frame} \end{document} 

output of above code

1
  • There might be ways to simplify the right appearance of the labels. I did not get into this too much. Commented May 4 at 14:56

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.