1

Hi I drew a bar chart and added the label onto each bar. However, as you can see I'm trying to state the relative difference between two facades, in some cases, i.e. the first two bars and the last one, the relative difference happens to be negative, how can I move the negative sign so that it doesn't go into the bar?

enter image description here Here's my MWE:

    \documentclass[11pt,a4paper]{article}
    \usepackage{tikz}
    \usepackage{pgfplots}
    \usepackage{pgfplotstable}
\begin{document}

        \begin{figure}[ht!]
        \begin{center}
        %0 - aramente   1 - Às vezes   2 - Quase sempre   4 - Sempre
        \pgfplotstableread{
          %2013-2014    %2012-2013  
        0 0          -5.2      
        1 0          -3.78      
        2 0        20.16      
        3 0        45.16
        4 0        19.68
        5 0        60.08
        6 0         15.99
        7 0         59.46
        8 0         -2.46

        }\dataset
        \begin{tikzpicture}
        \begin{axis}[ybar,
                width=16cm,
                height=8cm,
                ymin=-10,
                ymax=100,        
                ylabel={Relative difference (\%)},
                xtick=data,
                xticklabels = {
                    \strut GWP,
                    \strut ODP,
                    \strut POCP,
                    \strut AP,
                    \strut EP(T),
                    \strut EP(FW),
                    \strut EP(M),
                    \strut ADP,
                    \strut CED
                    %Category 5,
                    %Category 6
                },
                %xticklabel style={yshift=-10ex},
                major x tick style = {opacity=0},
                minor x tick style ={draw=none},
        %         minor tick length=2ex,
                every node near coord/.append style={
                        anchor=west,
                        rotate=90
                },
                legend entries={conventional facade, BIPV facade},
                legend columns=2,
                legend style={draw=none,nodes={inner sep=3pt},at={(0.5,-0.2)},anchor=north},
                ]
        \addplot[draw=black,fill=blue!20, nodes near coords] table[x index=0,y index=1] \dataset; %ano de 2013-2014
        \addplot[draw=black,fill=blue!60, nodes near coords] table[x index=0,y index=2] \dataset; %ano de 2012-2013
        \end{axis}
        \end{tikzpicture}
        \captionsetup{justification=centerlast, margin=10ex, labelfont=bf, format=plain, labelformat=default, labelsep=endash, font=small}
        \caption{Impacts by category relative to baseline building with conventional facade.}\label{relative}
        \end{center}
        \end{figure}
    \end{document}
  • For me, the command \captionsetup is unknown. Which package do you use for that? – bmv Sep 6 '18 at 8:36
3

The negative values go into the bar because by default the nodes near coords of them would be drawn below the negative bar, but because you stated anchor=west (on the rotated nodes) they are now all drawn above the anchor point. And the anchor point is still on the negative end for the negative bars. To overcome this you can create a style that changes the anchor point for the negative bars as shown below.

(Please also note that I further "optimized" your code a bit.)

% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
    \pgfplotsset{compat=1.3}
    \pgfplotstableread{
          %2013-2014    %2012-2013
        0 0          -5.2
        1 0          -3.78
        2 0        20.16
        3 0        45.16
        4 0        19.68
        5 0        60.08
        6 0         15.99
        7 0         59.46
        8 0         -2.46
    }\dataset
\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        ybar,
        width=16cm,
        height=8cm,
        ymin=-10,
        ymax=100,
        ylabel={Relative difference (\%)},
        xtick=data,
        % (you don't need to place `\strut's here for each entry ...
        xticklabels={
            GWP,
            ODP,
            POCP,
            AP,
            EP(T),
            EP(FW),
            EP(M),
            ADP,
            CED
        },
        %  ... just state this option)
        typeset ticklabels with strut,
        % (to also adjust the *placement* of the ticklabels when you don't
        %  want to show the major x ticks, first set the `major tick length'
        %  to zero ...
        major tick length=0pt,
        %  ... and restore the old value for the yticks afterwards)
        major y tick style={
            /pgfplots/major tick length=1.5mm,
        },
        % -----------------------------------------------------------------
        % adapted from <https://tex.stackexchange.com/a/141006/95441>
        nodes near coords always on top/.style={
            % a new feature since 1.9: allows to place markers absolutely:
            scatter/position=absolute,
            positive value/.style={
                at={(axis cs:\pgfkeysvalueof{/data point/x},\pgfkeysvalueof{/data point/y})},
%                draw,      % <-- for debugging only, to check if placement is correct
            },
            negative value/.style={
                at={(axis cs:\pgfkeysvalueof{/data point/x},0)},
%                draw,      % <-- for debugging only, to check if placement is correct
            },
            every node near coord/.append style={
                check values/.code={%
                    \begingroup
                    % this group is merely to switch to FPU locally. Might be
                    % unnecessary, but who knows.
                    \pgfkeys{/pgf/fpu}%
                    \pgfmathparse{\pgfplotspointmeta<0}%
                    \global\let\result=\pgfmathresult
                    \endgroup
                    %
                    % simplifies debugging:
                    %\show\result
                    %
                    \pgfmathfloatcreate{1}{1.0}{0}%
                    \let\ONE=\pgfmathresult
                    \ifx\result\ONE
                        % AH : our condition 'y < #1' is met.
                        \pgfkeysalso{/pgfplots/negative value}%
                    \else
                        % ok, proceed as usual.
                        \pgfkeysalso{/pgfplots/positive value}%
                    \fi
                },
                check values,
                anchor=west,
                rotate=90,
            },
        },
        nodes near coords={
            \pgfmathprintnumber[fixed zerofill,precision=1]{\pgfplotspointmeta}
        },
        nodes near coords always on top,
        % -----------------------------------------------------------------
        legend entries={
            conventional facade,
            BIPV facade,
        },
        legend columns=-1,
        legend style={
            draw=none,
            % (optimized the legend positioning, thus it is independent of the
            %  height/depth of the xticklabels. If you want to add a further
            %  yshift, use the optional second argument as in the commented
            %  version.)
            at={(xticklabel cs:0.5)},
%            at={(xticklabel cs:0.5,5pt)},
            anchor=north,
        },
    ]
        \addplot [draw=black,fill=blue!20] table [x index=0,y index=1] \dataset;
        \addplot [draw=black,fill=blue!60] table [x index=0,y index=2] \dataset;
    \end{axis}
\end{tikzpicture}
\end{document}

image showing the result of above code

  • Looks like this doesn't work if the bar gets cut off because it's longer than the shown area (ymin/xmin set). – Michael Nov 4 at 14:40
  • @Michael, that is true and a known behavior. I provided a solution for this e.g. at tex.stackexchange.com/a/365826/95441. – Stefan Pinnow Nov 4 at 17:41
1

You could add xshift=2ex to every node near coord/.append style:

   \documentclass[11pt,a4paper]{article}
    \usepackage{tikz}
    \usepackage{pgfplots}
    \usepackage{pgfplotstable}
\begin{document}

        \begin{figure}[ht!]
        \begin{center}
        %0 - aramente   1 - Às vezes   2 - Quase sempre   4 - Sempre
        \pgfplotstableread{
          %2013-2014    %2012-2013  
        0 0          -5.2      
        1 0          -3.78      
        2 0        20.16      
        3 0        45.16
        4 0        19.68
        5 0        60.08
        6 0         15.99
        7 0         59.46
        8 0         -2.46

        }\dataset
        \begin{tikzpicture}
        \begin{axis}[ybar,
                width=16cm,
                height=8cm,
                ymin=-10,
                ymax=100,        
                ylabel={Relative difference (\%)},
                xtick=data,
                xticklabels = {
                    \strut GWP,
                    \strut ODP,
                    \strut POCP,
                    \strut AP,
                    \strut EP(T),
                    \strut EP(FW),
                    \strut EP(M),
                    \strut ADP,
                    \strut CED
                    %Category 5,
                    %Category 6
                },
                %xticklabel style={yshift=-10ex},
                major x tick style = {opacity=0},
                minor x tick style ={draw=none},
        %         minor tick length=2ex,
                every node near coord/.append style={
                        anchor=west,
                        rotate=90,
                        xshift=2ex            
                },
                legend entries={conventional facade, BIPV facade},
                legend columns=2,
                legend style={draw=none,nodes={inner sep=3pt},at={(0.5,-0.2)},anchor=north},
                ]
        \addplot[draw=black,fill=blue!20, nodes near coords] table[x index=0,y index=1] \dataset; %ano de 2013-2014
        \addplot[draw=black,fill=blue!60, nodes near coords] table[x index=0,y index=2] \dataset; %ano de 2012-2013
        \end{axis}
        \end{tikzpicture}
        \caption{Impacts by category relative to baseline building with conventional facade.}\label{relative}
        \end{center}
        \end{figure}
    \end{document}
  • Your solution shits all nodes near coords upwards. This works in this case and doesn't look that bad, because there are only very small negative values (compared to the "large" positive ones). But if you change one value of a negative bar to be in the same range as the positive ones (and adjust ymin accordingly) your suggestion doesn't work well any more ... – Stefan Pinnow Sep 6 '18 at 10:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.