![tikzpicture:将一些 ybar 放在其他 ybar 后面](https://linux22.com/image/380663/tikzpicture%EF%BC%9A%E5%B0%86%E4%B8%80%E4%BA%9B%20ybar%20%E6%94%BE%E5%9C%A8%E5%85%B6%E4%BB%96%20ybar%20%E5%90%8E%E9%9D%A2.png)
我想这是一个简单的问题,但却找不到任何有帮助的答案。
我有以下 MWE:
\documentclass[tikz]{standalone}
\usepackage{filecontents}
\usepackage{pgfplots,pgfplotstable}
\begin{filecontents*}{temp.dat}
month;t1;t2;t3;t4
1;2.0;4.0;3.0;5.0
2;3.0;5.0;4.0;6.0
3;4.0;6.0;5.0;4.0
4;5.0;7.0;6.0;5.0
5;6.0;8.0;7.0;9.0
6;7.0;9.0;8.0;10.0
\end{filecontents*}
\begin{document}
\pgfplotstableread[col sep=semicolon]{temp.dat}{\temp}
\begin{tikzpicture}
\begin{axis}[
ybar,bar width=5pt
]
\addplot [fill=cyan] table [x=month,y=t1] {\temp};
\addplot [fill=gray] table [x=month,y=t2] {\temp};
\addplot [fill=blue] table [x=month,y=t3] {\temp};
\addplot [fill=black] table [x=month,y=t4] {\temp};
\end{axis}
\end{tikzpicture}
\end{document}
我希望 t2 出现在 t1 后面,t4 出现在 t3 后面。我知道 ybar 偏移,但我不想手动偏移每一个 ybar,我的原始代码还有更多 ybar。提前感谢任何帮助!
答案1
pgfplots
知道键bar shift auto
,它用于对多个条形图的条形进行分组。手册第 83 页显示了它的定义(我还将其复制到代码中以供参考)。基于此,这里是对成对重叠条形的一些重新定义。
注意:要用 t1 覆盖 t2 并用 t3 覆盖 t4,必须改变绘图的顺序。
\documentclass[tikz]{standalone}
\usepackage{filecontents}
\usepackage{pgfplots,pgfplotstable}
\begin{filecontents*}{temp.dat}
month;t1;t2;t3;t4
1;2.0;4.0;3.0;5.0
2;3.0;5.0;4.0;6.0
3;4.0;6.0;5.0;4.0
4;5.0;7.0;6.0;5.0
5;6.0;8.0;7.0;9.0
6;7.0;9.0;8.0;10.0
\end{filecontents*}
% original from the manual
%\pgfplotsset{
% /pgfplots/bar shift auto/.style={
% /pgf/bar shift={%
% % total width = n*w + (n-1)*skip
% % -> subtract half for centering
% -0.5*(\numplotsofactualtype*\pgfplotbarwidth + (\numplotsofactualtype-1)*(#1)) +
% % the ’0.5*w’ is for centering
% (.5+\plotnumofactualtype)*\pgfplotbarwidth + \plotnumofactualtype*(#1)
% },
% },
%}
\begin{document}
\pgfplotstableread[col sep=semicolon]{temp.dat}{\temp}
% full overlap, t2 must be drawn before t1 and t4 before t3
\pgfplotsset{
/pgfplots/bar shift auto/.style={
/pgf/bar shift={%
% total width = n/2*w + ((n/2)-1)*skip
% -> subtract half for centering
-0.5*(\numplotsofactualtype/2*\pgfplotbarwidth + ((\numplotsofactualtype/2)-1)*(#1)) +
% the ’0.5*w’ is for centering
(.5+round((\plotnumofactualtype+1)/2)-1)*\pgfplotbarwidth + (round((\plotnumofactualtype+1)/2)-1)*(#1)
},
},
}
\begin{tikzpicture}
\begin{axis}[
title=full overlap,
ybar,bar width=5pt
]
\addplot [fill=gray] table [x=month,y=t2] {\temp};
\addplot [fill=cyan] table [x=month,y=t1] {\temp};
\addplot [fill=black] table [x=month,y=t4] {\temp};
\addplot [fill=blue] table [x=month,y=t3] {\temp};
\end{axis}
\end{tikzpicture}
% half overlap, front on the left
\pgfplotsset{
/pgfplots/bar shift auto/.style={
/pgf/bar shift={%
% total width = n/2*w*1.5 + ((n/2)-1)*skip
% need to add 0.5*skip here to correct centering
% -> subtract half for centering
-0.5*(\numplotsofactualtype/2*\pgfplotbarwidth*1.5 + (\numplotsofactualtype/2)*(#1)) +
% the ’0.5*w’ is for centering
(.5+round((\plotnumofactualtype+1)/2)-1)*\pgfplotbarwidth*1.5 +
iseven(\plotnumofactualtype)*\pgfplotbarwidth*0.5 +
(round((\plotnumofactualtype+1)/2)-1)*(#1)
},
},
}
\begin{tikzpicture}
\begin{axis}[
title={half overlap, front on left},
ybar,bar width=5pt
]
\addplot [fill=gray] table [x=month,y=t2] {\temp};
\addplot [fill=cyan] table [x=month,y=t1] {\temp};
\addplot [fill=black] table [x=month,y=t4] {\temp};
\addplot [fill=blue] table [x=month,y=t3] {\temp};
\end{axis}
\end{tikzpicture}
% half overlap, front on the right
\pgfplotsset{
/pgfplots/bar shift auto/.style={
/pgf/bar shift={%
% total width = n/2*w*1.5 + ((n/2)-1)*skip
% need to add 0.5*skip here to correct centering
% -> subtract half for centering
-0.5*(\numplotsofactualtype/2*\pgfplotbarwidth*1.5 + (\numplotsofactualtype/2)*(#1)) +
% the ’0.5*w’ is for centering
(.5+round((\plotnumofactualtype+1)/2)-1)*\pgfplotbarwidth*1.5 +
isodd(\plotnumofactualtype)*\pgfplotbarwidth*0.5 +
(round((\plotnumofactualtype+1)/2)-1)*(#1)
},
},
}
\begin{tikzpicture}
\begin{axis}[
title={half overlap, front on right},
ybar,bar width=5pt
]
\addplot [fill=gray] table [x=month,y=t2] {\temp};
\addplot [fill=cyan] table [x=month,y=t1] {\temp};
\addplot [fill=black] table [x=month,y=t4] {\temp};
\addplot [fill=blue] table [x=month,y=t3] {\temp};
\end{axis}
\end{tikzpicture}
\end{document}
答案2
如果您确实希望某些条形图位于其他条形图后面,为什么不使用 3D?(请注意,如果您尝试这种方法,则可能必须重新调整\gconv
,但您会被告知应该将其设置为哪个值。)
\documentclass[tikz,border=3.14pt]{standalone}
\usetikzlibrary{calc}
\usepackage{filecontents}
\usepackage{pgfplots,pgfplotstable}
\begin{filecontents*}{temp.dat}
month;t1;t2;t3;t4
1;2.0;4.0;3.0;5.0
2;3.0;5.0;4.0;6.0
3;4.0;6.0;5.0;4.0
4;5.0;7.0;6.0;5.0
5;6.0;8.0;7.0;9.0
6;7.0;9.0;8.0;10.0
\end{filecontents*}
\pgfplotsset{compat=1.16}
\begin{document}
\pgfplotstableread[col sep=semicolon]{temp.dat}{\resulttable}
\begin{tikzpicture}
\pgfplotsset{set layers}
\begin{axis}[% from section 4.6.4 of the pgfplotsmanual
view={20}{40},
width=320pt,
height=280pt,
z buffer=none,
xmin=0,xmax=6,
ymin=0.5,ymax=2,
zmin=0,zmax=24,
enlargelimits=upper,
xtick={1,...,6},
xticklabels={1,...,6},
ztick={0,10,20},
zticklabels={0,5,10}, % here one has to "cheat"
ytick=\empty,
% meaning that one has to put labels which are the actual value
% divided by 2. This is because the bars will be centered at these
% values
xtick=data,
xlabel={month},
ylabel={~},
zlabel={$t$},
minor tick num=1,
point meta=explicit,
colormap name=hot,
scatter/use mapped color={
draw=mapped color,fill=mapped color!70},
execute at begin plot={}
]
\def\gconv{8.57727}
\path let \p1=($(axis cs:0,0,1)-(axis cs:0,0,0)$) in
\pgfextra{\pgfmathsetmacro{\conv}{2*\y1}
\ifx\gconv\conv
\typeout{z-scale\space good!}
\else
\typeout{Kindly\space consider\space setting\space the\space
prefactor\space of\space z\space to\space \conv}
\fi
};
\pgfmathsetmacro{\DeltaX}{0.18}
\addplot3 [visualization depends on={
\gconv*z \as \myz}, % you'll get told how to adjust the prefactor
scatter/@pre marker code/.append style={/pgfplots/cube/size z=\myz},%
scatter/@pre marker code/.append style={/pgfplots/cube/size x=8pt},%
scatter/@pre marker code/.append style={/pgfplots/cube/size y=2pt},%
scatter,only marks,
mark=cube*,mark size=5,opacity=1]
table[x expr={\thisrow{month}-\DeltaX},y expr={1.6},z
expr={1*\thisrow{t3}},
meta expr={3}
] \resulttable;
\addplot3 [visualization depends on={
\gconv*z \as \myz}, % you'll get told how to adjust the prefactor
scatter/@pre marker code/.append style={/pgfplots/cube/size z=\myz},%
scatter/@pre marker code/.append style={/pgfplots/cube/size x=8pt},%
scatter/@pre marker code/.append style={/pgfplots/cube/size y=2pt},%
scatter,only marks,y=1,
mark=cube*,mark size=5,opacity=1]
table[x expr={\thisrow{month}+\DeltaX},y expr={1.6},z
expr={1*\thisrow{t4}},
meta expr={4}
] \resulttable;
\addplot3 [visualization depends on={
\gconv*z \as \myz}, % you'll get told how to adjust the prefactor
scatter/@pre marker code/.append style={/pgfplots/cube/size z=\myz},%
scatter/@pre marker code/.append style={/pgfplots/cube/size x=8pt},%
scatter/@pre marker code/.append style={/pgfplots/cube/size y=2pt},%
scatter,only marks,
mark=cube*,mark size=5,opacity=1]
table[x expr={\thisrow{month}-\DeltaX},y expr={1},z
expr={1*\thisrow{t1}},
meta expr={1}
] \resulttable;
\addplot3 [visualization depends on={
\gconv*z \as \myz}, % you'll get told how to adjust the prefactor
scatter/@pre marker code/.append style={/pgfplots/cube/size z=\myz},%
scatter/@pre marker code/.append style={/pgfplots/cube/size x=8pt},%
scatter/@pre marker code/.append style={/pgfplots/cube/size y=2pt},%
scatter,only marks,y=1,
mark=cube*,mark size=5,opacity=1]
table[x expr={\thisrow{month}+\DeltaX},y expr={1},z
expr={1*\thisrow{t2}},
meta expr={2}
] \resulttable;
\end{axis}
\end{tikzpicture}
\end{document}
答案3
正如 Max Snippe 指出的那样,还有一些问题尚待解决。但这可以为您提供一个起点。
我使用x expr
和bar shift = 0pt
选项来手动定义所请求的班次。
第一个tikzpicture
是直接应用,而第二个展示了一种将移位推广到更大数据集的方法。
\documentclass[tikz]{standalone}
\usepackage{filecontents}
\usepackage{pgfplots,pgfplotstable}
\begin{filecontents*}{temp.dat}
month;t1;t2;t3;t4
1;2.0;4.0;3.0;5.0
2;3.0;5.0;4.0;6.0
3;4.0;6.0;5.0;4.0
4;5.0;7.0;6.0;5.0
5;6.0;8.0;7.0;9.0
6;7.0;9.0;8.0;10.0
\end{filecontents*}
\begin{document}
\pgfplotstableread[col sep=semicolon]{temp.dat}{\temp}
% Manual application of shifts to hide bars behind previous ones
\begin{tikzpicture}
\begin{axis}[
ybar,bar width=5pt,bar shift=0pt
]
\addplot [fill=cyan] table [x expr = \thisrow{month}-0.15,y=t1] {\temp};
\addplot [fill=gray] table [x expr = \thisrow{month}-0.15,y=t2] {\temp};
\addplot [fill=blue] table [x expr = \thisrow{month}+0.15,y=t3] {\temp};
\addplot [fill=black] table [x expr = \thisrow{month}+0.15,y=t4] {\temp};
\end{axis}
\end{tikzpicture}
% Generalization using \foreach loop on indices and shift values
\begin{tikzpicture}
\begin{axis}[
ybar,bar width=5pt,bar shift=0pt
]
\foreach \ind/\shift [evaluate=\ind as \indd using int(\ind+1)] in {1/-0.15,3/0.15}{
\addplot [fill=cyan] table [x expr = \thisrow{month}+\shift,y=t\ind] {\temp};
\addplot [fill=gray] table [x expr = \thisrow{month}+\shift,y=t\indd] {\temp};
}
\end{axis}
\end{tikzpicture}
\end{document}