我的目标是生成这个条形图:
我能够将此图表作为我的 MWE:
\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{pgfplots}
\pgfplotsset{width=10cm,compat=1.6}
\usepackage{xifthen}
\usetikzlibrary{patterns}
\usepackage{filecontents}
\makeatletter
\pgfplotsset{
/pgfplots/flexible xticklabels from table/.code n args={3}{%
\pgfplotstableread[#3]{#1}\coordinate@table
\pgfplotstablegetcolumn{#2}\of{\coordinate@table}\to\pgfplots@xticklabels
\let\pgfplots@xticklabel=\pgfplots@user@ticklabel@list@x
}
}
\makeatother
% argument #1: any options
\newenvironment{customlegend}[1][]{%
\begingroup
% inits/clears the lists (which might be populated from previous
% axes):
\csname pgfplots@init@cleared@structures\endcsname
\pgfplotsset{#1}%
}{%
% draws the legend:
\csname pgfplots@createlegend\endcsname
\endgroup
}%
% makes \addlegendimage available (typically only available within an
% axis environment):
\def\addlegendimage{\csname pgfplots@addlegendimage\endcsname}
\begin{filecontents}{testdata.csv}
matrix P methodAfirstPhase methodAsecondPhase methodBfirstPhase methodBsecondPhase
a 2 3 7 2 5
a 4 1 4 1 3
b 2 2 6 1 5
b 4 1 2 1 1
\end{filecontents}
\begin{document}
\begin{tikzpicture}[remember picture]
\def\numpsPLOT{2}
\def\nummtx{2}
\foreach \matrixid/\P/\axisState/\barShift/\Pshift in {0/2//0/0, 0/4/hide axis/30/.1, 1/2/hide axis/70/.3, 1/4/hide axis/100/.4} {
\pgfkeys{/pgf/number format/.cd,fixed,precision=0}%
\pgfmathparse{\matrixid*\numpsPLOT-1}%
\pgfmathtruncatemacro\le{\pgfmathresult+1}%
\pgfmathparse{\matrixid*\numpsPLOT+\numpsPLOT}%
\pgfmathtruncatemacro\us{\pgfmathresult}%
\pgfmathparse{\nummtx*\numpsPLOT}%
\pgfmathtruncatemacro\ue{\pgfmathresult}%
\begin{axis}
[ ybar stacked,
\axisState,
bar shift=\barShift-100,
enlarge x limits=9,
ymin=0,ymax=11,
x filter/.code={\expandafter\ifnum \thisrow{P}=\P\else\def\pgfmathresult{}\fi},
flexible xticklabels from table={testdata.csv}{matrix}{}, %ignore chars={\%,\_}
x tick label style={font=\small,text width=1.7cm,align=center,rotate=45},
xtick=data,
nodes near coords*,
]
\addplot[black,fill=black!20] table
[ x expr=\coordindex,
y=methodAfirstPhase,
skip coords between index={-1}{\le}, skip coords between index={\us}{\ue}
] {testdata.csv};
\addplot[black,pattern=north west lines,] table
[ x expr=\coordindex,
y=methodAsecondPhase,
skip coords between index={-1}{\le}, skip coords between index={\us}{\ue}
] {testdata.csv};
\end{axis}
\begin{axis}
[ ybar stacked,
\axisState,
bar shift={\barShift+10-100},
enlarge x limits=9,
ymin=0,ymax=11,
x filter/.code={\expandafter\ifnum \thisrow{P}=\P\else\def\pgfmathresult{}\fi},
flexible xticklabels from table={testdata.csv}{matrix}{}, %ignore chars={\%,\_}
x tick label style={font=\small,text width=1.7cm,align=center,rotate=45},
xtick=data,
nodes near coords*,
]
\addplot[black,fill=black!40] table
[ x expr=\coordindex,
y=methodBfirstPhase,
skip coords between index={-1}{\le}, skip coords between index={\us}{\ue}
] {testdata.csv};
\addplot[black,fill=black!40,pattern=north east lines,] table
[ x expr=\coordindex,
y=methodBsecondPhase,
skip coords between index={-1}{\le}, skip coords between index={\us}{\ue}
] {testdata.csv};
\end{axis}
\node[below left] at (rel axis cs:0.65+\Pshift,1) {P=\P};
}
\end{tikzpicture}
\begin{tikzpicture}
\begin{customlegend}[legend columns=2,legend style={align=left,draw=none,column sep=2ex},legend entries={Method A $\Phi1$,Method B $\Phi1$,Method A $\Phi2$,Method B $\Phi2$}]
\addlegendimage{black,fill=black!20,area legend}
\addlegendimage{black,fill=black!40,area legend}
\addlegendimage{black,fill=black!50,area legend,pattern=north west lines,}
\addlegendimage{black,fill=black!0,area legend,pattern=north east lines,}
\end{customlegend}
\end{tikzpicture}
\end{document}
结果:
我想要的是:
存在三个问题:
1) 我希望矩阵名称放在相关条形图下方。我无法使用,symbolic x coords={a,b}
因为矩阵名称必须从数据文件加载。在我的 MWE 中,只有矩阵名称a
可见,但b
缺失。我通过移动条形图,bar shift=...
但无法移动 x 个刻度。有没有办法移动 x 个刻度?
2) 我无法在条形图内放置数字。矩阵名称和数字必须随着条形图的移动而移动bar shift=...
。(同样的问题)再次注意,我无法使用,symbolic x coords={a,b}
因为矩阵名称是根据数据文件动态确定的。
3) 我想根据条形图放置处理器编号,并且最好位于相应条形图的正上方或正下方。在我的 MWE 中,我已经手动放置了处理器编号。我想根据相关条形图自动放置。
在我原来的代码中,处理器的数量、矩阵名称、矩阵的数量……一切都可能改变,所以我的代码应该是灵活的。
答案1
我不知道你能多好地适应你的场景,解决方案并不那么优雅。为了给所有四个轴一个图例,它使用克里斯蒂安·费尔桑格的解决方案这个问题。
代码
\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{pgfplots}
\pgfplotsset{width=10cm,compat=1.6}
\usepackage{xifthen}
\usepackage{filecontents}
% argument #1: any options
\newenvironment{customlegend}[1][]{%
\begingroup
% inits/clears the lists (which might be populated from previous
% axes):
\csname pgfplots@init@cleared@structures\endcsname
\pgfplotsset{#1}%
}{%
% draws the legend:
\csname pgfplots@createlegend\endcsname
\endgroup
}%
% makes \addlegendimage available (typically only available within an
% axis environment):
\def\addlegendimage{\csname pgfplots@addlegendimage\endcsname}
\begin{filecontents}{testdata.csv}
matrix P methodAfirstPhase methodAsecondPhase methodBfirstPhase methodBsecondPhase
a 2 3 7 2 6
a 4 1 4 1 3
b 2 2 6 1 5
b 4 1 2 1 1
\end{filecontents}
\begin{document}
\begin{tikzpicture}[remember picture]
\begin{axis}
[ ybar stacked,
bar shift=-20pt,
ymin=0,ymax=11,
symbolic x coords={a,b},
x filter/.code={\expandafter\ifnum \thisrow{P}=4 \def\pgfmathresult{}\fi},
xtick={a,b},
enlarge x limits=0.5,
grid=major,
]
\addplot[black,fill=black!20] table
[ x=matrix,
y=methodAfirstPhase,
] {testdata.csv};
\addplot[black,fill=black!0] table
[ x=matrix,
y=methodAsecondPhase,
] {testdata.csv};
\end{axis}
\begin{axis}
[ ybar stacked,
bar shift=-8pt,
ymin=0,ymax=11,
symbolic x coords={a,b},
x filter/.code={\expandafter\ifnum \thisrow{P}=2 \def\pgfmathresult{}\fi},
hide axis,
enlarge x limits=0.5,
]
\addplot[black,fill=black!70] table
[ x=matrix,
y=methodBfirstPhase,
] {testdata.csv};
\addplot[black,fill=black!50] table
[ x=matrix,
y=methodBsecondPhase,
] {testdata.csv};
\end{axis}
\begin{axis}
[ ybar stacked,
bar shift=8pt,
ymin=0,ymax=11,
symbolic x coords={a,b},
x filter/.code={\expandafter\ifnum \thisrow{P}=2 \def\pgfmathresult{}\fi},
hide axis,
enlarge x limits=0.5,
]
\addplot[black,fill=black!20] table
[ x=matrix,
y=methodAfirstPhase,
] {testdata.csv};
\addplot[black,fill=black!0] table
[ x=matrix,
y=methodAsecondPhase,
] {testdata.csv};
\end{axis}
\begin{axis}
[ ybar stacked,
bar shift=20pt,
ymin=0,ymax=11,
symbolic x coords={a,b},
x filter/.code={\expandafter\ifnum \thisrow{P}=2 \def\pgfmathresult{}\fi},
hide axis,
enlarge x limits=0.5,
]
\addplot[black,fill=black!70] table
[ x=matrix,
y=methodBfirstPhase,
] {testdata.csv};
\addplot[black,fill=black!50] table
[ x=matrix,
y=methodBsecondPhase,
] {testdata.csv};
\node[below left] at (rel axis cs:0.25,1) {P=2};
\node[below right] at (rel axis cs:0.25,1) {P=4};
\node[below left] at (rel axis cs:0.75,1) {P=2};
\node[below right] at (rel axis cs:0.75,1) {P=4};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{customlegend}[legend entries={Method A (First Phase),Method B (First Phase),Method A (Second Phase),Method B (Second Phase)}]
\addlegendimage{black,fill=black!70,area legend}
\addlegendimage{black,fill=black!20,area legend}
\addlegendimage{black,fill=black!50,area legend}
\addlegendimage{black,fill=black!0,area legend}
\end{customlegend}
\end{tikzpicture}
\end{document}
输出
编辑1:要在条形图中放置数字,您可以使用point meta={rawy}
:
代码
\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{pgfplots}
\pgfplotsset{width=10cm,compat=1.6}
\usepackage{xifthen}
\usepackage{filecontents}
% argument #1: any options
\newenvironment{customlegend}[1][]{%
\begingroup
% inits/clears the lists (which might be populated from previous
% axes):
\csname pgfplots@init@cleared@structures\endcsname
\pgfplotsset{#1}%
}{%
% draws the legend:
\csname pgfplots@createlegend\endcsname
\endgroup
}%
% makes \addlegendimage available (typically only available within an
% axis environment):
\def\addlegendimage{\csname pgfplots@addlegendimage\endcsname}
\begin{filecontents}{testdata.csv}
matrix P methodAfirstPhase methodAsecondPhase methodBfirstPhase methodBsecondPhase
a 2 3 7 2 6
a 4 1 4 1 3
b 2 2 6 1 5
b 4 1 2 1 1
\end{filecontents}
\begin{document}
\begin{tikzpicture}[remember picture]
\begin{axis}
[ ybar stacked,
bar shift=-20pt,
ymin=0,ymax=11,
symbolic x coords={a,b},
x filter/.code={\expandafter\ifnum \thisrow{P}=4 \def\pgfmathresult{}\fi},
xtick={a,b},
enlarge x limits=0.5,
grid=major,
every node near coord/.append style={anchor=north,xshift=-20pt,font=\tiny},
nodes near coords,
]
\addplot[black,fill=black!20] table
[ x=matrix,
y=methodAfirstPhase,
] {testdata.csv};
\addplot[black,fill=black!0] table
[ x=matrix,
y=methodAsecondPhase,
point meta={rawy},
] {testdata.csv};
\end{axis}
\begin{axis}
[ ybar stacked,
bar shift=-8pt,
ymin=0,ymax=11,
symbolic x coords={a,b},
x filter/.code={\expandafter\ifnum \thisrow{P}=2 \def\pgfmathresult{}\fi},
hide axis,
enlarge x limits=0.5,
every node near coord/.append style={anchor=north,xshift=-8pt,font=\tiny},
nodes near coords,
]
\addplot[black,fill=black!70] table
[ x=matrix,
y=methodBfirstPhase,
] {testdata.csv};
\addplot[black,fill=black!50] table
[ x=matrix,
y=methodBsecondPhase,
point meta={rawy},
] {testdata.csv};
\end{axis}
\begin{axis}
[ ybar stacked,
bar shift=8pt,
ymin=0,ymax=11,
symbolic x coords={a,b},
x filter/.code={\expandafter\ifnum \thisrow{P}=2 \def\pgfmathresult{}\fi},
hide axis,
enlarge x limits=0.5,
every node near coord/.append style={anchor=north,xshift=8pt,font=\tiny},
nodes near coords,
]
\addplot[black,fill=black!20] table
[ x=matrix,
y=methodAfirstPhase,
] {testdata.csv};
\addplot[black,fill=black!0] table
[ x=matrix,
y=methodAsecondPhase,
point meta={rawy},
] {testdata.csv};
\end{axis}
\begin{axis}
[ ybar stacked,
bar shift=20pt,
ymin=0,ymax=11,
symbolic x coords={a,b},
x filter/.code={\expandafter\ifnum \thisrow{P}=2 \def\pgfmathresult{}\fi},
hide axis,
enlarge x limits=0.5,
every node near coord/.append style={anchor=north,xshift=20pt,font=\tiny},
nodes near coords,
]
\addplot[black,fill=black!70] table
[ x=matrix,
y=methodBfirstPhase,
] {testdata.csv};
\addplot[black,fill=black!50] table
[ x=matrix,
y=methodBsecondPhase,
point meta={rawy},
] {testdata.csv};
\node[below left] at (rel axis cs:0.25,1) {P=2};
\node[below right] at (rel axis cs:0.25,1) {P=4};
\node[below left] at (rel axis cs:0.75,1) {P=2};
\node[below right] at (rel axis cs:0.75,1) {P=4};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{customlegend}[legend entries={Method A (First Phase),Method B (First Phase),Method A (Second Phase),Method B (Second Phase)}]
\addlegendimage{black,fill=black!70,area legend}
\addlegendimage{black,fill=black!20,area legend}
\addlegendimage{black,fill=black!50,area legend}
\addlegendimage{black,fill=black!0,area legend}
\end{customlegend}
\end{tikzpicture}
\end{document}
输出
答案2
我添加了额外的字段来确定条形的位置,并添加了一个空轴来添加 x 刻度。请注意,这些额外的字段可以通过使用 预处理问题中的表格来自动生成pgfplotstable
。
\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{pgfplots}
\pgfplotsset{width=10cm,compat=1.6}
\usepackage{xifthen}
\usetikzlibrary{patterns}
\usepackage{filecontents}
\makeatletter
\pgfplotsset{
/pgfplots/flexible xticklabels from table/.code n args={3}{%
\pgfplotstableread[#3]{#1}\coordinate@table
\pgfplotstablegetcolumn{#2}\of{\coordinate@table}\to\pgfplots@xticklabels
\let\pgfplots@xticklabel=\pgfplots@user@ticklabel@list@x
}
}
\makeatother
% argument #1: any options
\newenvironment{customlegend}[1][]{%
\begingroup
% inits/clears the lists (which might be populated from previous
% axes):
\csname pgfplots@init@cleared@structures\endcsname
\pgfplotsset{#1}%
}{%
% draws the legend:
\csname pgfplots@createlegend\endcsname
\endgroup
}%
% makes \addlegendimage available (typically only available within an
% axis environment):
\def\addlegendimage{\csname pgfplots@addlegendimage\endcsname}
\begin{filecontents}{testdata.csv}
id idb matrix P methodAfirstPhase methodAsecondPhase methodBfirstPhase methodBsecondPhase
0 .5 a 2 3 7 2 5
1.5 2 a 4 1 4 1 3
3.5 4 b 2 2 6 1 5
5 5.5 b 4 1 2 1 1
\end{filecontents}
\begin{filecontents}{matrixnames.csv}
matrix xval yval
a 1.5 0
b 4.5 0
\end{filecontents}
\begin{document}
\begin{tikzpicture} [remember picture]
\def\numpsPLOT{2}
\def\nummtx{2}
\begin{axis}[ybar,
xticklabels from table={matrixnames.csv}{matrix},
xtick=data,ymin=0,ymax=11,xmin=0,xmax=10,]
\addplot table
[ x=xval,
y=yval
]{matrixnames.csv};
\end{axis}
\foreach \matrixid/\P/\axisState/\barShift/\Pshift in {0/2/hide axis/0/0, 0/4/hide axis/30/.1, 1/2/hide axis/70/.3, 1/4/hide axis/100/.4} {
\pgfkeys{/pgf/number format/.cd,fixed,precision=0}%
\pgfmathparse{\matrixid*\numpsPLOT-1}%
\pgfmathtruncatemacro\le{\pgfmathresult+1}%
\pgfmathparse{\matrixid*\numpsPLOT+\numpsPLOT}%
\pgfmathtruncatemacro\us{\pgfmathresult}%
\pgfmathparse{\nummtx*\numpsPLOT}%
\pgfmathtruncatemacro\ue{\pgfmathresult}%
\begin{axis}
[ ybar stacked,
\axisState,
enlarge x limits,
ymin=0,ymax=11,
x filter/.code={\expandafter\ifnum \thisrow{P}=\P\else\def\pgfmathresult{}\fi},
nodes near coords*,
xmin=0,
xmax=10,
]
\addplot[black,fill=black!20] table
[ % x expr=\coordindex,
x=id,
y=methodAfirstPhase,
skip coords between index={-1}{\le}, skip coords between index={\us}{\ue}
] {testdata.csv};
\addplot[black,pattern=north west lines,] table
[ x=id,
y=methodAsecondPhase,
skip coords between index={-1}{\le}, skip coords between index={\us}{\ue},
] {testdata.csv};
\end{axis}
\begin{axis}
[ ybar stacked,
\axisState,
enlarge x limits,
ymin=0,ymax=11,
x filter/.code={\expandafter\ifnum \thisrow{P}=\P\else\def\pgfmathresult{}\fi},
xtick=data,
nodes near coords*,
xmin=0,
xmax=10,
]
\addplot[black,fill=black!40] table
[ x=idb,
y=methodBfirstPhase,
skip coords between index={-1}{\le}, skip coords between index={\us}{\ue}
] {testdata.csv};
\addplot[black,fill=black!40,pattern=north east lines,] table
[ x=idb,
y=methodBsecondPhase,
skip coords between index={-1}{\le}, skip coords between index={\us}{\ue}
] {testdata.csv};
\end{axis}
}
\end{tikzpicture}
\begin{tikzpicture}
\begin{customlegend}[legend columns=2,legend style={align=left,draw=none,column sep=2ex},legend entries={Method A $\Phi1$,Method B $\Phi1$,Method A $\Phi2$,Method B $\Phi2$}]
\addlegendimage{black,fill=black!20,area legend}
\addlegendimage{black,fill=black!40,area legend}
\addlegendimage{black,fill=black!50,area legend,pattern=north west lines,}
\addlegendimage{black,fill=black!0,area legend,pattern=north east lines,}
\end{customlegend}
\end{tikzpicture}
\end{document}
输出: