我有几个数据文件,我想以以下方式绘制它们:
我通过以下代码实现了这一点:
\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
。