tikzpicture:将一些 ybar 放在其他 ybar 后面

tikzpicture:将一些 ybar 放在其他 ybar 后面

我想这是一个简单的问题,但却找不到任何有帮助的答案。

我有以下 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 exprbar 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}

相关内容