1

I would like to get the values from the the columns Cd, Cr, and Ni showing on their respective sections of the bars in the chart. I would like them to be aligned in the center of each section. I have used nodes near coords and \addplot with coordinates to show the values. The first three fit within the correct place but they are not centered. Furthermore, the subsequent \addplot show up in the wrong position. Could I get some help with this issue? Thank you in advance for the help. example of where my chart is at

Code is

\documentclass[border={0pt,0pt,0pt,0pt}]{standalone}

\usepackage{helvet}
\usepackage[eulergreek]{sansmath}
\usepackage{tikz,pgfplotstable}
\usetikzlibrary{patterns}
\pgfplotsset{compat=1.8,
 every axis/.style={axis on top},
 tick label style = {font=\sansmath\sffamily\small\itshape,xshift={-15}},
 every axis label = {font=\sansmath\sffamily},
 legend style = {font=\sansmath\sffamily},
 label style = {font=\sansmath\sffamily}, 
 }
\begin{document}

\pgfplotstableread{
Species                         Cd      Cr      Ni
V.\space c.\space cochiensis    3.67    2.16    2.27
L.\space teres                  2.76    0       0
L.\space s.\space claibornensis 2.52    0       1.94
A.\space pectorosa              2.34    0       1.34
L.\space subviridis             2.34    0       0
U.\space imbecillis             2.26    0.76    1.44
V.\space vibex                  2.21    0       1.58
C.\space fluminalis             1.39    0       0
P.\space casertanum             1.17    0       0
P.\space compressum             1.08    0       0
C.\space rhizophorae            0.40    0       0
P.\space favidens               0.24    0       0
L.\space marginalis             0.10    0       0
M.\space nervosa                0       1.08    1.82
R.\space cuneata                0       0.90    0
A.\space plicata                0       0.85    1.69
L.\space siliquoidea            0       0.80    1.42
M.\space falcata                0       0.42    1.63
H.\space perovalis              0       0       1.56
V.\space nebulosa               0       0       1.35
H.\space cumingii               0       -0.81   0
D.\space chilensis              0       -1.09   0
}\testdata

\begin{tikzpicture}
\begin{axis}[
            xbar stacked,
            xmin=-3,
            xmax=8,         
            xticklabel style=transparent,    
            xtick style=transparent,
            ytick style=transparent,            
            axis y line*=middle,
            every inner y axis line/.append style = {dotted, ultra thick},
            height=11cm,
            width=11.9cm,           
            enlarge y limits={abs=0.725},
            enlarge x limits={abs=0.725},            
            xlabel={RS = $\log (LC_{50\textit{Lf}}/LC_{50\textit{i}})$},             
            ytick=\empty,
            legend style={at={(0.8,0.6)},anchor=north west, draw=none},            
            nodes near coords,
            visualization depends on=x\as\myx,          
            nodes near coords align={center},
            every node near coord/.append style={anchor ={180-sign(\myx)*180},font=\footnotesize},
            point meta = explicit symbolic         
]
\addlegendimage{empty legend},
\addplot [fill=black!90!black!45] table [x=Cr, y expr=\coordindex] {\testdata};   % "First" column against the data index
\addplot [fill=black!90!black!20] table [x=Cd, y expr=\coordindex] {\testdata};
\addplot [fill=black!5] table [x=Ni, y expr=\coordindex] {\testdata};
\addplot [only marks,mark size=0pt,point meta=explicit symbolic,
    nodes near coords,nodes near coords style={anchor=east,font =\small\itshape}] 
    table[x expr={-1*ifthenelse(\thisrow{Cd}+\thisrow{Cr}+\thisrow{Ni}>0,
        \thisrow{Cd}+\thisrow{Cr}+\thisrow{Ni},0)},y expr=\coordindex,meta=Species]  {\testdata};
\addplot[black] coordinates{(2.16,0)[2.16]};%shows up well but not 'center'.
\addplot[black] coordinates{(3.67,0)[3.67]};%shows up well but not 'center'.
\addplot[black] coordinates{(2.27,0)[2.27]};%shows up well but not 'center'.
%
%all other \addplot entries from table.
%
\addplot[black] coordinates{(0,20)};
\addplot[black] coordinates{(-0.81,20)[-0.81]};%shows up on the wrong position. 
\addplot[black] coordinates{(0,20)};
\addplot[black] coordinates{(0,21)};
\addplot[black] coordinates{(-1.09,21)[-1.09]};%shows up on the wrong position.
\addplot[black] coordinates{(0,21)};


\addlegendentry{\hspace{-0.85cm}\textbf\small{Metals}},
\addlegendentry{Cr(VI)},
\addlegendentry{Cd(II)},
\addlegendentry{Ni(II)},
\end{axis}
\end{tikzpicture}

\end{document}
Emmo03
  • 105

1 Answers1

1

Out of the two points you raise I think one of them can be addressed rather easily. The issue is that these are stacked plots. However, it seems that you only want to show the x values. Then you seem to want to suppress the nodes if the bar is too small. This can be achieved with a style

\pgfplotsset{my meta/.style={point meta=\thisrow{#1},
every node near coord/.append style={%
 opacity={ifthenelse(abs(\csname my#1\endcsname)><threshold>,1,0)}}}}

where <threshold> is taken to be 0.5 in the below example. For the horizontal centering I use a variant of this solution.

\documentclass[border={0pt,0pt,0pt,0pt}]{standalone}

\usepackage{helvet}
\usepackage[eulergreek]{sansmath}
\usepackage{tikz,pgfplotstable}
\usetikzlibrary{patterns}
\pgfplotsset{compat=1.8,
 every axis/.style={axis on top},
 tick label style = {font=\sansmath\sffamily\small\itshape,xshift={-15}},
 every axis label = {font=\sansmath\sffamily},
 legend style = {font=\sansmath\sffamily},
 label style = {font=\sansmath\sffamily}, 
 }
\makeatletter
\pgfplotsset{
    calculate offset/.code={
        \pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}    
        \pgfmathsetmacro\testmacro{(10^\pgfplots@data@scale@trafo@EXPONENT@x)*%
         \csname my#1\endcsname/2*\pgfplots@x@veclength)}
        \pgfkeys{/pgf/fpu=false}
        },
    nodes near coords horizontally centered/.style={
        every node near coord/.append style={
            /pgfplots/calculate offset=#1,
            xshift=-\testmacro
        },
    }
}
\makeatother 

\begin{document}

\pgfplotstableread{
Species                         Cd      Cr      Ni
V.\space c.\space cochiensis    3.67    2.16    2.27
L.\space teres                  2.76    0       0
L.\space s.\space claibornensis 2.52    0       1.94
A.\space pectorosa              2.34    0       1.34
L.\space subviridis             2.34    0       0
U.\space imbecillis             2.26    0.76    1.44
V.\space vibex                  2.21    0       1.58
C.\space fluminalis             1.39    0       0
P.\space casertanum             1.17    0       0
P.\space compressum             1.08    0       0
C.\space rhizophorae            0.40    0       0
P.\space favidens               0.24    0       0
L.\space marginalis             0.10    0       0
M.\space nervosa                0       1.08    1.82
R.\space cuneata                0       0.90    0
A.\space plicata                0       0.85    1.69
L.\space siliquoidea            0       0.80    1.42
M.\space falcata                0       0.42    1.63
H.\space perovalis              0       0       1.56
V.\space nebulosa               0       0       1.35
H.\space cumingii               0       -0.81   0
D.\space chilensis              0       -1.09   0
}\testdata

\begin{tikzpicture}
\pgfplotsset{my meta/.style={point meta=\thisrow{#1},
nodes near coords horizontally centered=#1,
every node near coord/.append style={%
opacity={ifthenelse(abs(\csname my#1\endcsname)>0.5,1,0)}}}}
\begin{axis}[
            xbar stacked,
            xmin=-3,
            xmax=8,         
            xticklabel style=transparent,    
            xtick style=transparent,
            ytick style=transparent,            
            axis y line*=middle,
            every inner y axis line/.append style = {dotted, ultra thick},
            height=11cm,
            width=11.9cm,           
            enlarge y limits={abs=0.725},
            enlarge x limits={abs=0.725},            
            xlabel={RS = $\log (LC_{50\textit{Lf}}/LC_{50\textit{i}})$},             
            ytick=\empty,
            legend style={at={(0.8,0.6)},anchor=north west, draw=none},            
            nodes near coords,
            visualization depends on=x\as\myx, 
            visualization depends on=\thisrow{Cr}\as\myCr,
            visualization depends on=\thisrow{Cd}\as\myCd,
            visualization depends on=\thisrow{Ni}\as\myNi,         
            nodes near coords align={center},
            every node near coord/.append style={%anchor={180-sign(\myx)*180},
            font=\tiny},
]
\addlegendimage{empty legend},
\addplot [fill=black!90!black!45,my meta=Cr] table [x=Cr, y expr=\coordindex] {\testdata};   % "First" column against the data index
\addplot [fill=black!90!black!20,my meta=Cd] table [x=Cd, y expr=\coordindex] {\testdata};
\addplot [fill=black!5,my meta=Ni] table [x=Ni, y expr=\coordindex] {\testdata};
\addplot [only marks,mark size=0pt,point meta=explicit symbolic,
    nodes near coords,nodes near coords style={anchor=east,font=\small\itshape,opacity=1}] 
    table[x expr={-1*ifthenelse(\thisrow{Cd}+\thisrow{Cr}+\thisrow{Ni}>0,
        \thisrow{Cd}+\thisrow{Cr}+\thisrow{Ni},0)},y expr=\coordindex,meta=Species]  {\testdata};
\addlegendentry{\hspace{-0.85cm}\textbf\small{Metals}},
\addlegendentry{Cr(VI)},
\addlegendentry{Cd(II)},
\addlegendentry{Ni(II)},
\end{axis}
\end{tikzpicture}

\end{document}

enter image description here

  • That is amazing, thank you so much! Would reducing the font size allow me to display a few more values at least? I would like the values for Cr(VI) to show... – Emmo03 Jan 20 '20 at 03:24
  • 1
    @Emmo03 I think so, yes. You can try to set font=\tiny or use scale.The threshold is set with opacity={ifthenelse(\csname my#1\endcsname>1,1,0)}, so if you use opacity={ifthenelse(\csname my#1\endcsname>0.5,1,0)}, values larger than 0.5 will be shown. –  Jan 20 '20 at 03:28
  • Great! I will try with that to see how many more values I can get to show. Thank you so much again! – Emmo03 Jan 20 '20 at 03:31
  • 1
    @Emmo03 There was an error which I fixed now. –  Jan 20 '20 at 04:15
  • thanks! I noticed that the alignment shifted. Now it looks really neat. I am also trying to get the negative values showing, but then I get all the zeros too! can I establish some sort of threshold > 0 < so zero is out? – Emmo03 Jan 20 '20 at 04:26
  • 1
    @Emmo03 That's easy: take the absolute value: opacity={ifthenelse(abs(\csname my#1\endcsname)>0.5,1,0)}. I edited the post accordingly. –  Jan 20 '20 at 04:27
  • oh I see! cool. That is a lot of certainty for a cat in such a quantum superposition! I learn a lot thanks to your help. I have even been able to help someone creating a chart the other day. – Emmo03 Jan 20 '20 at 04:35
  • Just had a thought for those values that do not fit in their bars. Would it be possible to place them outside the bars? can I set up nodes near coords for that when there is every node near coord/append style already defined? – Emmo03 Jan 20 '20 at 05:58
  • 1
    @Emmo03 You can place them outside but this makes the plot very busy, doesn't it? Some of the thin bars are surrounded by other things in all directions. –  Jan 20 '20 at 06:12
  • yeah it is true. I am quite restricted with the number of pages though. I need to condense all that info in one chart. I also thought of referencing them (a,b,c,..) and provide the values as a footnote? – Emmo03 Jan 20 '20 at 06:20
  • 1
    @Emmo03 I do not know. The graph is to give the reader a feeling for the values. If you want to show all values precisely, you can use a table. –  Jan 20 '20 at 06:22
  • I actually have the table, but was hoping to get all the info in the chart. I think you are right, and it is too much. I will probably use the chart to convey the visual comparison among metals and use the table for the actual values. Thanks for the advice! – Emmo03 Jan 20 '20 at 06:29