2

I am trying to make a 2D bar plot with the bars coloured according to another third variable using the colorbar i.e. the color of the bar has nothing to do with the variables shown but some other variable.

I have previously managed to get a scatter plot with the colours matching but am unsure how to fill the bars with the appropriate colour.

\documentclass[tikz,border=3.14pt]{standalone}
\usetikzlibrary{calc}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.16}
\usepgfplotslibrary{colormaps}

\pgfplotsset{colormap access=direct}
\tikzset{mycolor/.code={\pgfplotscolormapdefinemappedcolor{#1}}}

\begin{document}


\begin{tikzpicture}
\begin{axis}[colorbar, colormap/jet,
colorbar style={
            ylabel={Years},
            ylabel style={anchor=west, text width=3cm, rotate=270},
        },
    width=15cm,
height=9cm,
    legend style={at={(0.5,-0.15)},
      anchor=north,legend columns=-1},
    xlabel={$x$},
    symbolic y coords={A, B, C, D, E, F, G, H, I, J, K, L, M},
    ylabel = {$y$},
    xtick={0,5,10,15,20,25,20,35},
    xmax=35,
    xmin=0,
    ytick={A, B, C, D, E, F, G, H, I, J, K, L, M},
          bar shift=0pt,
    ]

\addplot+ [xbar, point meta=\thisrow{years}, 
    visualization depends on={\thisrow{years} \as \myvalue},fill= mapped color]  table {
    x       y     years
    22.6   A      1.800
    31.7   B      1.300
    4.8    C      2.000
    16.7   D      2.300
    3.9    E      4.100
    0.244333 F    0.61
    3.622143 G    9.1
    0.566104 H    57
    2.98 I       29.8
    1.85 J        3.7
    0.334255 K    6.7
    1.9 L         38
    0.395 M        0
  };

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

enter image description here

So in this picture, "G" should be blue but "I" should be green.

Thank you in advance :) and apologies if the answer is really simple.

  • 1
    Hello ! It seems your question is related to this one – BambOo Apr 7 at 17:15
  • Hey, thanks for the comment, appreciate it. Just trying to adapt it now but I'm not sure as for those solutions the colour was related to the value shown on the plot; I'll update my question to be clearer. Thank you though :) – Owen Apr 7 at 19:09
  • 1
    I just reopened this question. If this is a duplicate then IMHO 95% of the open questions are. – user194703 Apr 8 at 1:11
2

You can use Jake's solution #1, which BambOo linked to, almost one-to-one if you replace the symbolic coordinates by \coordindex.

\documentclass[tikz,border=3.14pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usepgfplotslibrary{colormaps}
\begin{document}
\begin{tikzpicture}
  \begin{axis}[
    colorbar, colormap/jet,
    colorbar style={
            ylabel={Years},
            ylabel style={anchor=west, text width=3cm, rotate=270},
        },
    scatter,
    scatter src=x,
    only marks,
    clip mode=individual,
    scatter/@pre marker code/.append code={
            \pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
            \pgfmathsetmacro\negheight{-\pgfplotspointmeta}         
            \fill [draw=black] 
             (axis direction cs:0,0.3) rectangle (axis direction cs:\negheight,-0.3);
            \pgfplotsset{mark=none}
        },
    xmin=0,
    width=15cm,
    height=9cm,
    legend style={at={(0.5,-0.15)},
      anchor=north,legend columns=-1},
    xlabel={$x$},
    %symbolic y coords={A, B, C, D, E, F, G, H, I, J, K, L, M},
    ylabel = {$y$},
    xtick={0,5,10,15,20,25,20,35},
    xmax=35,
    xmin=0,
    ytick={0,...,12},
    yticklabels={A, B, C, D, E, F, G, H, I, J, K, L, M},
  ]
  \addplot table[x=x,y expr=\coordindex] {
    x       y     years
    22.6   A      1.800
    31.7   B      1.300
    4.8    C      2.000
    16.7   D      2.300
    3.9    E      4.100
    0.244333 F    0.61
    3.622143 G    9.1
    0.566104 H    57
    2.98 I       29.8
    1.85 J        3.7
    0.334255 K    6.7
    1.9 L         38
    0.395 M        0
  };
  \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

With symbolic coordinates it is probably also doable but more efforts.

ADDENDUM: Here is one way to spell out BambOo's great idea.

\documentclass[tikz,border=3.14pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usepgfplotslibrary{colormaps}
\pgfplotsset{/pgfplots/colormap={jet}{rgb255(0cm)=(0,0,128) rgb255(1cm)=(0,0,255)
rgb255(3cm)=(0,255,255) rgb255(5cm)=(255,255,0) rgb255(7cm)=(255,0,0)
rgb255(8cm)=(128,0,0)}}
\newsavebox\JetColorBar
% convert 'hot' -> \result 
\pgfplotscolormaptoshadingspec{jet}{12.5cm}\jetresult
% define and use a shading in pgf: 
\def\tempb{\pgfdeclarehorizontalshading{tempshading}{1cm}}% 
% where '\result' is inserted as last argument: 
\expandafter\tempb\expandafter{\jetresult}% 
\sbox\JetColorBar{\pgfuseshading{tempshading}}%
\begin{document}
\begin{tikzpicture}
  \begin{axis}[
    colorbar, colormap/jet,
    colorbar style={
            ylabel={Years},
            ylabel style={anchor=west, text width=3cm, rotate=270},
        },
    scatter,
    scatter src=x,
    only marks,
    clip mode=individual,
    scatter/@pre marker code/.append code={
            \pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
            \pgfmathsetmacro\negheight{-\pgfplotspointmeta} 
            \clip
             (axis direction cs:0,0.3) rectangle (axis direction cs:\negheight,-0.3);
            \path  (axis direction cs:\negheight,0)
             node[anchor=west,outer sep=0pt,inner sep=0pt]{\usebox\JetColorBar};        
            \pgfplotsset{mark=none}
        },
    xmin=0,
    width=15cm,
    height=9cm,
    legend style={at={(0.5,-0.15)},
      anchor=north,legend columns=-1},
    xlabel={$x$},
    %symbolic y coords={A, B, C, D, E, F, G, H, I, J, K, L, M},
    ylabel = {$y$},
    xtick={0,5,10,15,20,25,20,35},
    xmax=35,
    xmin=0,
    ytick={0,...,12},
    yticklabels={A, B, C, D, E, F, G, H, I, J, K, L, M},
  ]
  \addplot table[x=x,y expr=\coordindex] {
    x       y     years
    22.6   A      1.800
    31.7   B      1.300
    4.8    C      2.000
    16.7   D      2.300
    3.9    E      4.100
    0.244333 F    0.61
    3.622143 G    9.1
    0.566104 H    57
    2.98 I       29.8
    1.85 J        3.7
    0.334255 K    6.7
    1.9 L         38
    0.395 M        0
  };
  \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

Or with point meta different from x.

\documentclass[tikz,border=3.14pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usepgfplotslibrary{colormaps}
\begin{document}
\begin{tikzpicture}
  \begin{axis}[
    colorbar, colormap/jet,
    colorbar style={
            ylabel={Years},
            ylabel style={anchor=west, text width=3cm, rotate=270},
        },
    scatter,
    scatter src=x,
    only marks,
    clip mode=individual,
    visualization depends on=\thisrow{x}\as\myx,
    scatter/@pre marker code/.append code={
            \pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
            \pgfmathsetmacro\negheight{-1*\myx}         
            \fill [draw=black] 
             (axis direction cs:0,0.3) rectangle (axis direction cs:\negheight,-0.3);
            \pgfplotsset{mark=none}
        },
    xmin=0,
    width=15cm,
    height=9cm,
    legend style={at={(0.5,-0.15)},
      anchor=north,legend columns=-1},
    xlabel={$x$},
    %symbolic y coords={A, B, C, D, E, F, G, H, I, J, K, L, M},
    ylabel = {$y$},
    xtick={0,5,10,15,20,25,20,35},
    xmax=35,
    xmin=0,
    ytick={0,...,12},
    yticklabels={A, B, C, D, E, F, G, H, I, J, K, L, M},
    point meta=\thisrow{years}
  ]
  \addplot table[x=x,y expr=\coordindex] {
    x       y     years
    22.6   A      1.800
    31.7   B      1.300
    4.8    C      2.000
    16.7   D      2.300
    3.9    E      4.100
    0.244333 F    0.61
    3.622143 G    9.1
    0.566104 H    57
    2.98 I       29.8
    1.85 J        3.7
    0.334255 K    6.7
    1.9 L         38
    0.395 M        0
  };
  \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

| improve this answer | |
  • Based on your proposal, I tried shading the bars with left/right color= stuff and with color of colormap, but I can never reproduce the colorbar. The idea was to draw a rectangle as large as the axis then clip at the right size to keep the correct colors. But I could not find a way ... – BambOo Apr 7 at 22:58
  • 2
    @BambOo This really just Jake's proposal which I am copying here. So you want to replace each bar by a clipped color bar? Is this what you are trying? – user194703 Apr 7 at 23:22
  • 1
    @BambOo Thanks for the kind words! Thanks to this comment I "discovered" (for myself, of course) the command \pgfplotscolormaptoshadingspec. This basically allows one to access all these nice color schemes with TikZ. – user194703 Apr 8 at 7:57
  • 1
    @BambOo This is just copied from the manual. (But in this case it really just means that \jetresult gets expanded before \tempb.) – user194703 Apr 8 at 8:15
  • 1
    @Owen Seems like I misread the question, but this just a trivial switch, see the last part of the updated answer. – user194703 Apr 26 at 21:51

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.