我有以下数据:
Year upper lower
2007 3.2 -.81
2008 2.0 -.29
2009 1.8 -.95
2010 -.5 -3.9
2011 -2. -7.3
我想要一个填充上下区域之间的图形。我想要的效果类似于在 pgfplots 中的两条曲线之间填充。。
第一个问题: 如果我的数据按如下方式组织,我想我可以轻松地使用填充命令:
Year upper
2007 3.2
2008 2.0
2009 1.8
2010 -.5
2011 -2.
2011 -7.3
2010 -3.9
2009 -.95
2008 -.29
2007 -.81
有没有办法使用 pgfplots 或任何其他工具来绘制这种数据格式的上下边界之间带有阴影的图形?
第二个问题: 另外,我希望 2009.5 和 2010.5 之间的阴影区域有不同的颜色。有没有办法在不将这些点包含在数据中的情况下实现此目的?
在拼凑了本站上其他问题的解决方案后,我找到的最接近的解决方案是下面这个最小的非工作示例。我能够为新的插值创建宏,并希望将它们连接到现有表中,但无法在 tableread 命令中使用这些宏。我仍然远远没有达到我的目标,但这对我来说是高级的东西。
\documentclass[border=5mm]{standalone}
\usepackage{pgfplots, pgfplotstable}
\usetikzlibrary{calc}
\pgfplotstableread{
Year upper lower
2007 3.2 -.81
2008 2.0 -.29
2009 1.8 -.95
2010 -.5 -3.9
2011 -2. -7.3
}\datatable
\begin{document}
% Interpolate 2009.5 upper
\pgfplotstablegetelem{2}{lower}\of\datatable
\pgfmathsetmacro{\y}{\pgfplotsretval}
\pgfplotstablegetelem{3}{lower}\of\datatable
\pgfmathsetmacro{\x}{\pgfplotsretval}
\pgfmathsetmacro{\firstupper}{\y-(\y-\x)/2}
% Interpolate 2009.5 lower
\pgfplotstablegetelem{2}{upper}\of\datatable
\pgfmathsetmacro{\y}{\pgfplotsretval}
\pgfplotstablegetelem{3}{upper}\of\datatable
\pgfmathsetmacro{\x}{\pgfplotsretval}
\pgfmathsetmacro{\firstlower}{\y-(\y-\x)/2}
% Interpolate 2010.5 upper
\pgfplotstablegetelem{3}{lower}\of\datatable
\pgfmathsetmacro{\y}{\pgfplotsretval}
\pgfplotstablegetelem{4}{lower}\of\datatable
\pgfmathsetmacro{\x}{\pgfplotsretval}
\pgfmathsetmacro{\firstupper}{\y-(\y-\x)/2}
% Interpolate 2010.5 lower
\pgfplotstablegetelem{3}{upper}\of\datatable
\pgfmathsetmacro{\y}{\pgfplotsretval}
\pgfplotstablegetelem{4}{upper}\of\datatable
\pgfmathsetmacro{\x}{\pgfplotsretval}
\pgfmathsetmacro{\secondlower}{\y-(\y-\x)/2}
\begin{tikzpicture}
\begin{axis}[
/pgf/number format/1000 sep={},
xmin=2007,
xmax=2011,
ymin=-8,
ymax=5,
enlarge x limits=false
]
\addplot [draw=none, stack plots=y,forget plot] table [y=lower] {\datatable};
\addplot [draw=none, fill=gray, opacity=.5,stack plots=y] table [y expr=\thisrow{upper}-\thisrow{lower}] {\datatable} \closedcycle;
\addplot [stack plots=y, stack dir=minus,forget plot, draw=none] table [y expr=\thisrow{upper}-\thisrow{lower}] {\datatable};
\end{axis}
\begin{axis}[
/pgf/number format/1000 sep={},
xmin=2007,
xmax=2011,
ymin=-8,
ymax=5,
enlarge x limits=false
]
\addplot [draw=none, stack plots=y, forget plot, restrict x to domain=2009.5:2010.5] table [y=lower]{\datatable};
\addplot [draw=none, fill=white,opacity=.5,stack plots=y, restrict x to domain=2009.5:2010.5] table [y expr=\thisrow{upper}-\thisrow{lower}] {\datatable} \closedcycle;
\end{axis}
\end{tikzpicture}
\end{document}
谢谢!
答案1
对于第一个问题:您可以使用stack plots=y
将图堆叠在一起,并将其放在\closedcycle
第二个图的末尾以填充两条曲线之间的区域:
\documentclass[border=5mm]{standalone}
\usepackage{pgfplots, pgfplotstable}
\pgfplotstableread{
Year upper lower
2007 3.2 -.81
2008 2.0 -.29
2009 1.8 -.95
2010 -.5 -3.9
2011 -2. -7.3
}\datatable
\begin{document}
\begin{tikzpicture}
\begin{axis}[
/pgf/number format/1000 sep={},
enlarge x limits=false
]
\addplot [draw=none, stack plots=y] table [y=lower] {\datatable};
\addplot [draw=none, fill=orange, stack plots=y] table [y expr=\thisrow{upper}-\thisrow{lower}] {\datatable} \closedcycle;
\end{axis}
\end{tikzpicture}
\end{document}
答案2
这是MWE
使用另一个工具Asymptote
。它从文件加载数据,填充主要区域,然后分离出由real innerLeft=2009.5;
和real innerRight=2010.5;
时间戳定义的内部部分并用不同的颜色填充。
% yearplot.tex :
%
\begin{filecontents*}{data.dat}
Year upper lower
2007 3.2 -.81
2008 2.0 -.29
2009 1.8 -.95
2010 -.5 -3.9
2011 -2. -7.3
\end{filecontents*}
%
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}
\begin{document}
\begin{figure}
\begin{asy}
size(300,160,IgnoreAspect);
import graph;
import fontsize;
defaultpen(fontsize(9pt));
string filename="data.dat";
pen lpen=mediumblue;
pen upen=lightblue;
pen lpenB=mediumred;
pen upenB=lightred;
pen axispen=darkblue+0.6bp+squarecap;
real innerLeft=2009.5;
real innerRight=2010.5;
file fin=input(filename).line();
string s=fin.line(); // read title
string[] title=split(s);
real[][] a=fin.dimension(0,0); // read the data matrix
a=transpose(a); // a[0] = years, a[1] = upper, a[2] = lower
// +++ main UpperRegion
guide upper=graph(a[0],a[1]);
guide lower=graph(a[0],a[2]);
guide mid=graph(a[0],0.5*(a[1]+a[2]));
guide LowerRegion=lower--reverse(mid)--cycle;
guide UpperRegion=upper--reverse(mid)--cycle;
fill(LowerRegion,lpen);
fill(UpperRegion,upen);
// --- main UpperRegion
// +++ inner UpperRegion
real[] timesLeft;
real[] timesRight;
timesLeft=times(LowerRegion,innerLeft);
timesRight=times(LowerRegion,innerRight);
guide innerLower=subpath(LowerRegion,timesLeft[0],timesRight[0]);
guide innerMiddle=subpath(LowerRegion,timesRight[1],timesLeft[1]);
timesLeft=times(UpperRegion,innerLeft);
timesRight=times(UpperRegion,innerRight);
guide innerUpper=subpath(UpperRegion,timesLeft[0],timesRight[0]);
fill(innerLower--innerMiddle--cycle,lpenB);
fill(innerUpper--innerMiddle--cycle,upenB);
// --- inner UpperRegion
xaxis(Label(title[0],0.5),YEquals(min(a[2])-1),min(a[0])-0.5,max(a[0])+0.5,axispen,LeftTicks(Step=1));
yaxis(XEquals(min(a[0])-0.5),min(a[2])-1,max(a[1]),axispen,RightTicks(Step=2,step=1));
shipout(bbox(Fill(lightyellow)));
\end{asy}
\end{figure}
\end{document}
%
% Process:
%
% pdflatex yearplot.tex
% asy yearplot-*.asy
% pdflatex yearplot.tex
答案3
我最终通过收集 Jake 对其他问题的回答的点点滴滴来回答我的问题的第二部分。在这个过程中我学到了很多东西。我相信使用循环可以更有效地完成这一点,但这已经达到了我的目的。
\documentclass[border=5mm]{standalone}
\usepackage{pgfplots, pgfplotstable}
\usetikzlibrary{calc}
\pgfplotstableread{
Year upper lower
2007 3.2 -.81
2008 2.0 -.29
2009 1.8 -.95
2010 -.5 -3.9
2011 -2. -7.3
}\datatable
\newcommand\addrows[1]{
\pgfplotstablegetelem{2}{upper}\of#1
\pgfmathsetmacro{\y}{\pgfplotsretval}
\pgfplotstablegetelem{3}{upper}\of#1
\pgfmathsetmacro{\x}{\pgfplotsretval}
\pgfmathsetmacro{\firstnewupper}{\y-(\y-\x)/2}
\pgfplotstablegetelem{2}{lower}\of#1
\pgfmathsetmacro{\y}{\pgfplotsretval}
\pgfplotstablegetelem{3}{lower}\of#1
\pgfmathsetmacro{\x}{\pgfplotsretval}
\pgfmathsetmacro{\firstnewlower}{\y-(\y-\x)/2}
\pgfplotstablegetelem{3}{upper}\of#1
\pgfmathsetmacro{\y}{\pgfplotsretval}
\pgfplotstablegetelem{4}{upper}\of#1
\pgfmathsetmacro{\x}{\pgfplotsretval}
\pgfmathsetmacro{\secondnewupper}{\y-(\y-\x)/2}
\pgfplotstablegetelem{3}{lower}\of#1
\pgfmathsetmacro{\y}{\pgfplotsretval}
\pgfplotstablegetelem{4}{lower}\of#1
\pgfmathsetmacro{\x}{\pgfplotsretval}
\pgfmathsetmacro{\secondnewlower}{\y-(\y-\x)/2}
\edef\makenew{\noexpand\pgfplotstableread[header=has colnames,col sep=comma,row sep=crcr]{
Year,upper,lower\noexpand\\
2009.5,\firstnewupper,\firstnewlower\noexpand\\
2010.5,\secondnewupper,\secondnewlower\noexpand\\
}\noexpand\interpolated}
\makenew
\pgfplotstablevertcat#1{\interpolated}
\pgfplotstablesort[sort cmp=float >]{#1}{#1}
}
\begin{document}
\addrows{\datatable}
\begin{tikzpicture}
\begin{axis}[
/pgf/number format/1000 sep={},
xmin=2007,
xmax=2011,
ymin=-8,
ymax=5,
enlarge x limits=false
]
\addplot [draw=none, stack plots=y,forget plot] table [y=lower] {\datatable};
\addplot [draw=none, fill=gray, opacity=.5,stack plots=y] table [y expr=\thisrow{upper}-\thisrow{lower}] {\datatable} \closedcycle;
\addplot [stack plots=y, stack dir=minus,forget plot, draw=none] table [y expr=\thisrow{upper}-\thisrow{lower}] {\datatable};
\end{axis}
\begin{axis}[
/pgf/number format/1000 sep={},
xmin=2007,
xmax=2011,
ymin=-8,
ymax=5,
enlarge x limits=false
]
\addplot [draw=none, stack plots=y, forget plot, restrict x to domain=2009.5:2010.5] table [y=lower]{\datatable};
\addplot [draw=none, fill=white,opacity=.5,stack plots=y, restrict x to domain=2009.5:2010.5] table [y expr=\thisrow{upper}-\thisrow{lower}] {\datatable} \closedcycle;
\end{axis}
\end{tikzpicture}
\end{document}