更改绘图 pgfplots 中的颜色,从 pgfplotstable 加载数据

更改绘图 pgfplots 中的颜色,从 pgfplotstable 加载数据

我有以下内容:

\documentclass[11pt,twoside,openright]{memoir}

\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepackage{xcolor}

\definecolor{color1}{RGB}{146,200,180}
\definecolor{color2}{RGB}{124,206,89}

\pgfplotstableread[col sep=comma]{
start,end,Name,color
0,600,fooer,color1
600,1020,foo2bar,color2
}\loadedtable


\begin{document}

\begin{tikzpicture}
\begin{axis}[
    xbar, xmin=0,
    y axis line style = { opacity = 0 },
    tickwidth         = 0pt,
    width=12cm, height=3.5cm, enlarge y limits=0.5,
    symbolic y coords={fooer,foo2bar},
    ytick=data, xbar stacked,
    bar shift=0pt,
    y dir=reverse,
    xtick={1, 500, 1000},
    xticklabels={1 ms, 500 ms, 1 s}
]

\addplot [draw=none, forget plot] table [x=end, y=Name]{\loadedtable};
\addplot+[color1] table [x expr=\thisrow{start}-\thisrow{end}, y=Name]{\loadedtable};
\end{axis}
\end{tikzpicture}

\end{document}

在此处输入图片描述

如您所见,我的color1被选中了,但现在我只希望“fooer”是color1和“foo2bar”是color2。但是,如果我将行更改为:

\addplot+[\thisrow{color}] table [x expr=\thisrow{start}-\thisrow{end}, y=Name]{\loadedtable};

我得到:

! Undefined control sequence.
\pgfkeyscurrentkey ->\thisrow 
                              {color}
l.35 \addplot+[\thisrow{color}] t
                                 able [x expr=\thisrow{start}-\thisrow{end},...

? 

我怎样才能使图表用不同的颜色着色?


编辑:我决定最简单的方法一定是摆脱pgfplots依赖关系,并分别添加每行我想要的颜色。所以现在我有了这个:(我添加了第三个,因为我注意到了奇怪的行为)

\documentclass[11pt,twoside,openright]{memoir}

\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{xcolor}

\definecolor{color1}{RGB}{146,200,180}
\definecolor{color2}{RGB}{124,206,89}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
    xbar, xmin=0,
    y axis line style = { opacity = 0 },
    tickwidth         = 0pt,
    width=12cm, height=3.5cm, enlarge y limits=0.5,
    symbolic y coords={a,b,c},
    ytick=data, xbar stacked,
    bar shift=0pt,
    y dir=reverse,
    xtick={1, 500, 1000},
    xticklabels={1 ms, 500 ms, 1 s}
]


\addplot+[color1]                 coordinates { (600,a) };

\addplot [draw=none, forget plot] coordinates { (600,b) };
\addplot+[color2]                 coordinates { (1020,b) };

\addplot [draw=none, forget plot] coordinates { (600,c) };
\addplot+[color2]                 coordinates { (900,c) };


\end{axis}
\end{tikzpicture}

\end{document}

在此处输入图片描述 但是,现在坐标出现了一些非常奇怪的情况。为什么它们没有放在我告诉它放置条形的位置?带有颜色 2 的两个条形应该立即从彼此下方开始,而且它们也太靠右了……

哦,只打印了 a,没有打印 b 和 c......

答案1

正如您已经注意到的,您需要为每个条形图绘制一个图,以便获得单独的颜色。借助这个答案您可以自动执行此操作。此外,无需重新输入名称symbolic y coords。一些额外的代码会从表中读取颜色并将其传递给图表。

因为它是一个堆叠图,并且第一个条形图从 0 开始,所以不需要\addplot [draw=none, forget plot]。事实上,这会导致编辑问题。

代码中有一些注释,应该可以解释一些事情。但是如果你有任何问题,请随时提问。

代码:

\documentclass[11pt,twoside,openright]{memoir}

\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepackage{xcolor}

\definecolor{color1}{RGB}{146,200,180}
\definecolor{color2}{RGB}{124,206,89}

% from https://tex.stackexchange.com/a/128040/110842
% filter to only get the current row in \pgfplotsinvokeforeach
\pgfplotsset{
    select row/.style={
        x filter/.code={\ifnum\coordindex=#1\else\def\pgfmathresult{}\fi}
    }
}


\pgfplotstableread[col sep=comma]{
start,end,Name,color
0,300,fooer,color1
300,800,foo2bar,color2
800,1020,bar2baz,green!60!red
}\loadedtable
% getting number of data rows - 1
\pgfplotstablegetrowsof{\loadedtable}
\pgfmathsetmacro{\tablerows}{int(\pgfplotsretval-1)}



\begin{document}

\begin{tikzpicture}
\begin{axis}[
    xbar, xmin=0,
    y axis line style = { opacity = 0 },
    tickwidth         = 0pt,
    width=12cm, height=3.5cm, enlarge y limits=0.5,
    % next two lines also from https://tex.stackexchange.com/a/128040/110842,
    ytick={0,...,\tablerows},
    yticklabels from table={\loadedtable}{Name},
    xbar stacked,
    bar shift=0pt,
    y dir=reverse,
    xtick={1, 500, 1000},
    xticklabels={1 ms, 500 ms, 1 s},
]

\pgfplotsinvokeforeach{0,...,\tablerows}{
    % get color from table, commands defined must be individual for each plot
    % because the color is used in \end{axis} and therefore would otherwise
    % use the last definition
    \pgfplotstablegetelem{#1}{color}\of{\loadedtable}
    \expandafter\edef\csname barcolor.#1\endcsname{\pgfplotsretval}
    \addplot+[color=\csname barcolor.#1\endcsname] table [select row=#1, x expr=\thisrow{end}-\thisrow{start}, y expr=#1]{\loadedtable};
}
\end{axis}
\end{tikzpicture}

\end{document}

结果:

在此处输入图片描述

答案2

好的,xbar stacked意思就是这样。每个新小节都从上一个小节的结束处开始,IE,如果不去掉这个位置,条形图就无法从同一位置开始。现在,有了这个变化,我们不再需要先绘制一个不可见的条形图,然后从该位置继续绘制。相反,我们将首先绘制整个条形图,然后绘制一个白色条形图以删除我们不想要的东西。遗憾的是,我发现绘制白色条形图的唯一方法是先绘制一个用白色填充的条形图,然后绘制一个带有白色轮廓的条形图。因此,整个事情变成了这样:

\begin{document}

\begin{tikzpicture}
\begin{axis}[
    xbar, xmin=0,
    y axis line style = { opacity = 0 },
    tickwidth         = 0pt,
    width=12cm, height=3.5cm, enlarge y limits=0.5,
    symbolic y coords={a,b,c},
    ytick=data,
    bar shift=0pt,
    y dir=reverse,
    xtick={1, 500, 1000},
    xticklabels={1 ms, 500 ms, 1 s}
]


\addplot+[color1, forget plot]    coordinates { (600,a) };

\addplot+[color2, forget plot]    coordinates { (1020,b) };
\addplot [white, forget plot] coordinates { (600,b) };
\addplot+[white, forget plot] coordinates { (600,b) };

\addplot+[color2, forget plot]    coordinates { (900,c) };
\addplot [white, forget plot] coordinates { (600,c) };
\addplot+[white, forget plot] coordinates { (600,c) };

\end{axis}
\end{tikzpicture}

\end{document}

在此处输入图片描述

答案3

关于开始帖子的“表格图”。

  1. 如果刻度名称在表中,则无需执行这样的操作:(
    symbolic y coords={fooer,foo2bar,...}, 这不是一个好的风格!)

反而:

ytick={0,...,\RowsNo}, % <---- !
yticklabels from table={\loadedtable}{Name}, 
  1. 您可以读出颜色列并使用它来定义颜色。

(为清晰起见,此处单独说明)

% Define Colors separatly
\xdef\tempcolor{black}% 
\pgfplotsinvokeforeach{0,...,\RowsNo}{%%
\pgfplotstablegetelem{#1}{Color}\of{\loadedtable}
\xdef\tempcolor{\ifx \pgfplotsretval\empty \tempcolor \else \pgfplotsretval \fi}
\colorlet{barcolor#1}{\tempcolor}% define
%\colorbox{\tempcolor}{\tempcolor}, % show test 1
}%%
%\colorbox{barcolor3}{Text}, % show test 2

过滤器

\pgfplotsset{
select row/.style={
x filter/.code={\ifnum\coordindex=#1\else\def\pgfmathresult{}\fi}
}                }

进而

\pgfplotsinvokeforeach{0,...,\RowsNo}{%%  
\addplot[fill=barcolor#1] table [select row=#1, 
x expr=\thisrow{start}-\thisrow{end}, 
y expr=#1
] {\loadedtable};
}%%

条形图以定义的颜色单独绘制。

为了查看效果,表格(在开始帖子的有点奇怪的 MWE 中)扩展了几行:

在此处输入图片描述

\documentclass[a4paper]{article}
\usepackage{pgfplots, pgfplotstable}
\pgfplotsset{compat=1.17}
\pgfplotsset{
select row/.style={
x filter/.code={\ifnum\coordindex=#1\else\def\pgfmathresult{}\fi}
}                }
 
\begin{document}


\definecolor{color1}{RGB}{146,200,180}
\definecolor{color2}{RGB}{124,206,89}

\pgfplotstableread[col sep=comma]{
start,   end,      Name,   Color
0,        600,      foo,       color1
600,    1020,     bar,      color2
700,    1020,     foo2,       
0,        700,      bar2,     red
700,    1020,     foo3,        
700,    1020,     bar3,     
700,    1020,     foo4,     blue
700,    1020,     bar4,     blue
700,    1020,     foo4,     
700,    1020,     bar4,     orange
}\loadedtable
\pgfplotstablegetrowsof{\loadedtable}
\pgfmathtruncatemacro{\RowsNo}{\pgfplotsretval-1}

% Define Colors separatly
\xdef\tempcolor{black}% 
\pgfplotsinvokeforeach{0,...,\RowsNo}{%%
\pgfplotstablegetelem{#1}{Color}\of{\loadedtable}
\xdef\tempcolor{\ifx \pgfplotsretval\empty \tempcolor \else \pgfplotsretval \fi}
\colorlet{barcolor#1}{\tempcolor}% define
%\colorbox{\tempcolor}{\tempcolor}, % show test 1
}%%
%\colorbox{barcolor3}{Text}, % show test 2

\begin{tikzpicture}
\begin{axis}[
xbar, xmin=0,
    y axis line style = { opacity = 0 },
%    tickwidth         = 0pt,
width=12cm,  height=3cm+3.5cm, % with that, ....
bar width=5pt, %... you would need sth. like that. 
enlarge y limits=0.5,
 %   ytick=data, 
%    symbolic y coords={foo,bar},  % No!
ytick={0,...,\RowsNo}, % <---- !
yticklabels from table={\loadedtable}{Name}, % Yes!
%    xbar stacked,
    bar shift=0pt,
    y dir=reverse,
%    xtick={1, 500, 1000},  % strange, because does not match...
xticklabels={1 ms, 500 ms, 1 s} % strange....
]
% Old:
%\addplot [draw=none, forget plot] table [x=end, y=Name]{\loadedtable};
%\addplot+[color1] table [x expr=\thisrow{start}-\thisrow{end}, y expr=\coordindex]{\loadedtable};

% New:
\pgfplotsinvokeforeach{0,...,\RowsNo}{%%  
\addplot[fill=barcolor#1] table [select row=#1, 
x expr=\thisrow{start}-\thisrow{end}, 
y expr=#1
] {\loadedtable};
}%%
\end{axis}
\end{tikzpicture}
\end{document}

相关内容