pgfplots:在同一张图中以正 y 方向和负 y 方向堆叠图

pgfplots:在同一张图中以正 y 方向和负 y 方向堆叠图

我有几个数据文件,我想以以下方式绘制它们:

在此处输入图片描述

我通过以下代码实现了这一点:

\documentclass{minimal}
\usepackage{pgfplots,filecontents}

\begin{filecontents}{total.dos}
0  0  0  0  0  0  0  0   
1  2  0 -2  0  2  0 -2  
2  4  0 -4  0  4  0 -4  
3  2  0 -2  0  2  0 -2  
4  0  0  0  0  0  0  0 
5  1  0 -1  0  0  0  0 
6  2  0 -2  0  0  0  0 
7  1  0 -1  0  0  0  0 
8  0  0  0  0  0  0  0 
\end{filecontents}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[xlabel={Energy [eV]}, ylabel={Intensity}, no markers]
    \addplot [fill=red,draw=none] table [x index=0,y index=5] {total.dos};
    \addplot [fill=red,draw=red,fill opacity=0.25] table [x index=0,y index=1] {total.dos};
    \addplot [fill=red,draw=none] table [x index=0, y index=7] {total.dos};
    \addplot [fill=red,draw=red,fill opacity=0.25] table [x index=0,y index=3] {total.dos};
  \end{axis}
\end{tikzpicture}
\end{document}

我的问题: 我怎样才能堆叠这些图?

它看起来应该类似于:

在此处输入图片描述

问题是,常规堆叠不起作用,因为这会堆叠所有数据addplot,从而导致输出错误,因为y我的数据中某些列为正值,而某些列为负值x,并且pgfplots只在一个方向(正值或负值)堆叠图表。但我需要创建pgfplots一些组addplot,而在相应的组内没有堆叠,然后让它堆叠这些组。这可能吗?

更新: 我修改了问题的标题,因为评论部分的讨论表明,关键点是同时pgfplots在正方向和负方向上制作情节。这样我就能按照我想要的方式呈现情节。y

答案1

也许下面的内容接近您想要的。诀窍是在堆叠图中仅添加正列,在假装共享相同轴的另一个图中仅添加负列。要工作,可见轴和不可见轴必须具有相同的域。我还使用了单位 pgfplots 库来分离单位。

\documentclass{standalone}
\usepackage{pgfplots,filecontents}
\usepgfplotslibrary{units}
\pgfplotsset{width=6cm,compat=newest}

\begin{filecontents}{total.dos}
0  0  0  0  0  0  0  0   
1  2  0 -2  0  2  0 -2  
2  4  0 -4  0  4  0 -4  
3  2  0 -2  0  2  0 -2  
4  0  0  0  0  0  0  0 
5  1  0 -1  0  0  0  0 
6  2  0 -2  0  0  0  0 
7  1  0 -1  0  0  0  0 
8  0  0  0  0  0  0  0 
\end{filecontents}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
  stack plots=y,
  xlabel={Energy},
  x unit={eV},
  ylabel={Intensity},
  no markers,
  ymin=-10,
  ymax=10
]
  \addplot [fill=red,draw=none] table [x index=0,y index=5] {total.dos}\closedcycle;
  \addplot [fill=blue,draw=none,fill opacity=0.25] table [x index=0,y index=1] {total.dos}\closedcycle;
\end{axis}
\begin{axis}[
  stack plots=y,
  no markers,
  ymin=-10,
  ymax=10,
  xtick=\empty,
  ytick=\empty,
  axis x line=none,
  axis y line=none
]
  \addplot [fill=red,draw=none] table [x index=0, y index=7] {total.dos}\closedcycle;
  \addplot [fill=blue,draw=none,fill opacity=0.25] table [x index=0,y index=3] {total.dos}\closedcycle;
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

为了完整起见,我将为我自己的问题添加一个不同的答案,因为它解决了仅在一个y方向上堆叠而不需要第二个轴的问题。实际上,如果数据文件包含正值和负值,则可以同时pgfplots在正方向和负方向上堆叠。y

我在进一步了解该pgfplotstable软件包时偶然发现了这个解决方案。实际上,正如 Mark 在他的一条评论中所建议的那样,通过使用外部工具(如 python 或 bash)来操作数据可以实现相同的结果。我更喜欢让它LaTeX完成这项工作,这样我就可以直接使用我的数据文件。

我的解决方案:

\documentclass{standalone}   

\usepackage{pgfplots}   
\pgfplotsset{width=6cm,compat=newest}
\usepgfplotslibrary{units}

\usepackage{pgfplotstable}
\usepackage{xcolor}
\colorlet{lightred}{red!25!white}
\colorlet{lightblue}{blue!25!white}

\usepackage{filecontents}

\begin{filecontents}{total.dos}
0  0  0  0  0  0  0  0   
1  2  0 -2  0  2  0 -2  
2  4  0 -4  0  4  0 -4  
3  2  0 -2  0  2  0 -2  
4  0  0  0  0  0  0  0 
5  1  0 -1  0  0  0  0 
6  2  0 -2  0  0  0  0 
7  1  0 -1  0  0  0  0 
8  0  0  0  0  0  0  0 
\end{filecontents}

\pgfplotstableread{total.dos}\total

% sort original file from highest to lowest value
\pgfplotstablesort[sort cmp=float >]{\totalsorted}{\total}

% first auxiliary table derived from \total: \totaldummy
\pgfplotstableset{
create on use/x/.style={create col/copy column from table={\total}{[index] 0}},
create on use/dummya/.style={create col/copy column from table={\total}{[index] 1}},
create on use/dummyb/.style={create col/copy column from table={\total}{[index] 3}},
create on use/a/.style={create col/copy column from table={\total}{[index] 5}},
create on use/b/.style={create col/copy column from table={\total}{[index] 7}},
create on use/c/.style={create col/expr={\thisrow{dummya} - \thisrow{a}}},
create on use/d/.style={create col/expr={\thisrow{dummyb} - \thisrow{b}}}}
% create a new table:
\pgfplotstablenew[columns={x, dummya, dummyb, a, b, c, d}] {\pgfplotstablegetrowsof{\total}} {\totaldummy}

% second auxiliary table derived from \totalsorted: \totalsorteddummy
\pgfplotstableset{
create on use/x/.style={create col/copy column from table={\totalsorted}{[index] 0}},
create on use/dummya/.style={create col/copy column from table={\totalsorted}{[index] 3}},
create on use/dummyb/.style={create col/copy column from table={\totalsorted}{[index] 1}},
create on use/a/.style={create col/copy column from table={\totalsorted}{[index] 7}},
create on use/b/.style={create col/copy column from table={\totalsorted}{[index] 5}},
create on use/c/.style={create col/expr={\thisrow{dummya} - \thisrow{a}}},
create on use/d/.style={create col/expr={\thisrow{dummyb} - \thisrow{b}}}}
% create a new table:
\pgfplotstablenew[columns={x, dummya, dummyb, a, b, c, d}] {\pgfplotstablegetrowsof{\total}} {\totalsorteddummy}

% Concatenate the two dummy tables
\pgfplotstablevertcat{\result}{\totaldummy}
\pgfplotstablevertcat{\result}{\totalsorteddummy}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
  stack plots=y,
  xlabel={Energy},
  ylabel={Intensity},
  x unit={eV}
]
\addplot [no markers, fill=lightblue, draw=blue] table [x=x, y=c] {\result};
\addplot [no markers, fill=blue, draw=blue] table [x=x, y=a] {\result};
\addplot [no markers, fill=lightred, draw=red] table [x=x, y=c] {\result};
\addplot [no markers, fill=red, draw=red] table [x=x, y=a] {\result};
\end{axis}
\end{tikzpicture}

\end{document}

得到如下图片:

在此处输入图片描述

这样,我便获得了我想要的效果:图的右叶颜色比左叶浅,浅色区域用较深的线条覆盖。为了获得正确的效果,必须根据值对数据值进行排序x。这是通过使用\pgfplotstablesort[sort cmp=float >]{\resulttable}{\table or filename}从最高值到最低值对数据进行排序来实现的x。如果不对值进行排序,则会出现以下效果:

在此处输入图片描述

draw因此,如果使用相同的颜色,fill则可以省去排序步骤draw=none

相关内容