我有几条曲线/数据集(通过蒙特卡罗模拟获得),它们具有 x 相关的 y 误差,我想绘制它们并以某种方式指示这些误差。由于每条曲线都包含大量数据点,且误差相当小,因此使用普通的误差线似乎不是最有信息量/最美观的解决方案。相反,我认为用(局部)线粗细(或 y 方向的粗细)指示误差会更好。例如,可以通过绘制 y(x)+dy(x) 和 y(x)-dy(x) 并在两条曲线之间填充来完成。但是如何在 Pgfplots 中做到这一点(以一种相当简单的方式 - 记住:我有几条曲线!)?
我的问题可能有点类似于这个但我不知道如何进行我的情况所需的表格操作(在 Pgfplots 中)。
下面是我的数据文件的一个简化示例:
x y dy
0 2 0.1
1 4 0.5
2 3 0.2
3 3 0.3
答案1
您可以使用堆叠图绘制不确定性带,然后再绘制实际数据线。首先,您要\addplot table [y expr=\thisrow{<data col>}-\thisrow{<error col}] {<datatable>};
确定下限,然后
\addplot [fill=<colour>] table [y expr=2*\thisrow{<error col}] {<datatable>} \closedcycle;
填充下限和上限之间的区域。
这两个\addplot
命令可以包装在宏中来生成图表,如下所示:
\newcommand{\errorband}[5][]{ % x column, y column, error column, optional argument for setting style of the area plot
\pgfplotstableread[col sep=comma, skip first n=2]{#2}\datatable
% Lower bound (invisible plot)
\addplot [draw=none, stack plots=y, forget plot] table [
x={#3},
y expr=\thisrow{#4}-\thisrow{#5}
] {\datatable};
% Stack twice the error, draw as area plot
\addplot [draw=none, fill=gray!40, stack plots=y, area legend, #1] table [
x={#3},
y expr=2*\thisrow{#5}
] {\datatable} \closedcycle;
% Reset stack using invisible plot
\addplot [forget plot, stack plots=y,draw=none] table [x={#3}, y expr=-(\thisrow{#4}+\thisrow{#5})] {\datatable};
}
您可以使用以下方式生成带有误差带的图
\errorband[<plot options>]{<data file>}{<x column>}{<y column>}{<error column>}
下面是绘制北部和南部海冰平均范围。
Fetterer, F.、K. Knowles、W. Meier、M. Savoie 和 AK Windnagel。2017 年,每日更新。海冰指数,第 3 版。[数据/北+南/月]。美国科罗拉多州博尔德。NSIDC:国家冰雪数据中心。doi:https://doi.org/10.7265/N5K072F8。
\documentclass{article}
\usepackage{pgfplots, pgfplotstable}
\begin{document}
\newcommand{\errorband}[5][]{ % x column, y column, error column, optional argument for setting style of the area plot
\pgfplotstableread[col sep=comma, skip first n=2]{#2}\datatable
% Lower bound (invisible plot)
\addplot [draw=none, stack plots=y, forget plot] table [
x={#3},
y expr=\thisrow{#4}-2*\thisrow{#5}
] {\datatable};
% Stack twice the error, draw as area plot
\addplot [draw=none, fill=gray!40, stack plots=y, area legend, #1] table [
x={#3},
y expr=4*\thisrow{#5}
] {\datatable} \closedcycle;
% Reset stack using invisible plot
\addplot [forget plot, stack plots=y,draw=none] table [x={#3}, y expr=-(\thisrow{#4}+2*\thisrow{#5})] {\datatable};
}
\begin{tikzpicture}
\begin{axis}[
compat=1.5.1,
no markers,
enlarge x limits=false,
ymin=0,
xlabel=Day of the Year,
ylabel=Sea Ice Extent\quad/\quad $10^6\,\mathrm{km}^2$,
legend entries={
$\pm$ 2 Standard Deviation,
NH 1997 to 2000 Average,
$\pm$ 2 Standard Deviation,
SH 1997 to 2000 Average,
NH 2012,
SH 2012
},
legend reversed,
legend pos=outer north east,
legend cell align=left,
x post scale=1.2
]
% Northern Hemisphere Average
\errorband[orange, opacity=0.5]{NH_seaice_extent_climatology_1979-2000.csv}{0}{3}{4}
% Northern Hemisphere 2012
\addplot [thick, orange!50!black] table [
x index=0,
y index=3,
skip first n=2,
col sep=comma,
] {NH_seaice_extent_climatology_1979-2000.csv};
% Southern Hemisphere Average
\errorband[cyan, opacity=0.5]{SH_seaice_extent_climatology_1979-2000.csv}{0}{3}{4}
% Southern Hemisphere 2012
\addplot [thick, cyan!50!black] table [
x index=0,
y index=3,
skip first n=2,
col sep=comma,
] {SH_seaice_extent_climatology_1979-2000.csv};
\addplot [ultra thick,red] table [
col sep=comma,
skip first n=367,
x expr=\coordindex,
y index=3
] {NH_seaice_extent_nrt.csv};
\addplot [ultra thick,blue] table [
col sep=comma,
skip first n=367,
x expr=\coordindex,
y index=3
] {SH_seaice_extent_nrt.csv};
%
\end{axis}
\end{tikzpicture}
\end{document}
更新
目前可用的数据涵盖了 1981 年至 2010 年海冰的平均范围。为了可重复性,可以对 LaTeX 代码进行如下更新(不包括 NH 和 SH 2012 线图):
$\pm$ 2 Standard Deviation,
NH 1981 to 2010 Average,
$\pm$ 2 Standard Deviation,
SH 1981 to 2010 Average
},
legend reversed,
legend pos=outer north east,
legend cell align=left,
x post scale=1.2
]
% Northern Hemisphere Average
\errorband[orange, opacity=0.5]{N_seaice_extent_climatology_1981-2010_v3.0.csv}{0}{1}{2}
% Northern Hemisphere 2012
\addplot [thick, orange!50!black] table [
x index=0,
y index=1,
skip first n=2,
col sep=comma,
] {fig/north.csv};
% Southern Hemisphere Average
% \errorband[<plot options>]{<data file>}{<x column>}{<y column>}{<error column>}
\errorband[cyan, opacity=0.5]{S_seaice_extent_climatology_1981-2010_v3.0.csv}{0}{1}{2}
% Southern Hemisphere 2012
\addplot [thick, cyan!50!black] table [
x index=0,
y index=1,
skip first n=2,
col sep=comma,
] {S_seaice_extent_climatology_1981-2010_v3.0.csv};
答案2
您可以使用mesh
变化的绘图line width
。但是,这会导致从一个线段到下一个线段的过渡不平滑。但也许是可行的:
如果你有较小的数据集,标记可以隐藏转换:
以下是代码:
\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.5}
\begin{document}
\begin{tikzpicture}
% avoid false-positive compilation errors:
\def\pgfplotspointmetatransformed{1000}
\begin{axis}[ymin=0,ymax=10]
\addplot+[
mesh,
blue,
%no marks,
every mark/.append style={line width=1pt,mark size=4pt,fill=blue!80!black},
shader=flat corner,
line width=1pt+5pt*\pgfplotspointmetatransformed/1000
]
table[point meta=\thisrow{dy}] {
x y dy
0 2 0.1
1 4 0.5
2 3 0.2
3 3 0.3
};
\end{axis}
\end{tikzpicture}
\end{document}
关键思想是 (a) 绘图mesh
绘制单独的线段,并且 (b)以完全规范化的方式\pgfplotspointmetatransformed
包含数据:最小的元数据条目(此处为 0.1)为,最大的元数据条目(此处为 0.5)为。 中间的值是线性插值的。 因此,我们可以像上面一样安全地使用它们。point meta
\pgfplotspointmetatransformed=0
\pgfplotspointmetatransformed=1000
line width
请注意,这些选项是在无法使用这一点元宏的上下文中评估的。为此,我将其全局定义为 1000(对于这些上下文来说应该没问题)。
答案3
最近我一直在玩这个fillbetween
图书馆,我认为它对于这种情况来说是理想的。
该答案的灵感来自上述 Jake 的回答,但使用了'1.10 版本fillbetween
中引入的库,pgfplots
而不是堆叠图。
输出:
该errorband
宏接受六个强制参数:数据表名称、x 列、y 列、错误列、线和错误带颜色以及错误带不透明度。
它的工作原理是为误差的上边界和下边界创建不可见的辅助图,并命名它们以供库使用fillbetween
。fillbetween
使用颜色和不透明度参数作为误差带设置。最后,它使用提供的颜色在误差带顶部绘制 y 列。
辅助图和误差带fillbetween
图被忽略,因此它们不包含在图例中。这样可以轻松使用errorband
,紧接着\addlegendentry
(或\legend
在最后)生成图例。
(未显示数据。)
解决方案:
\documentclass[x11names]{standalone}
\usepackage{pgfplots,pgfplotstable}
\usepgfplotslibrary{fillbetween}
\pgfplotsset{compat=1.10}
% Takes six arguments: data table name, x column, y column, error column,
% color and error bar opacity.
% ---
% Creates invisible plots for the upper and lower boundaries of the error,
% and names them. Then uses fill between to fill between the named upper and
% lower error boundaries. All these plots are forgotten so that they are not
% included in the legend. Finally, plots the y column above the error band.
\newcommand{\errorband}[6]{
\pgfplotstableread{#1}\datatable
\addplot [name path=pluserror,draw=none,no markers,forget plot]
table [x={#2},y expr=\thisrow{#3}+\thisrow{#4}] {\datatable};
\addplot [name path=minuserror,draw=none,no markers,forget plot]
table [x={#2},y expr=\thisrow{#3}-\thisrow{#4}] {\datatable};
\addplot [forget plot,fill=#5,opacity=#6]
fill between[on layer={},of=pluserror and minuserror];
\addplot [#5,thick,no markers]
table [x={#2},y={#3}] {\datatable};
}
\begin{document}
\begin{tikzpicture}%
\begin{axis}[%
width=10cm,
height=10cm,
scale only axis,
xlabel={$x$},
ylabel={$y$},
enlarge x limits=false,
grid=major,
legend style={
column sep=3pt,
nodes={right},
legend pos=south east,
},
]
\errorband{./data.dat}{0}{1}{2}{Firebrick2}{0.4}
\addlegendentry{Data}
\errorband{./data.dat}{0}{3}{4}{SpringGreen4}{0.4}
\addlegendentry{More data}
\end{axis}
\end{tikzpicture}%
\end{document}
性能注意事项:
对于那些仍在阅读的人,我认为绘制不可见的图只是为了命名它们,这会降低其效率。如果有人知道如何替换它:
\addplot [name path=pluserror,draw=none,no markers,forget plot]
table [x={#2},y expr=\thisrow{#3}+\thisrow{#4}] {\datatable};
类似这样的内容:
\path[name path=pluserror] table [x={#2},y expr=\thisrow{#3}+\thisrow{#4}] {\datatable};
那就太好了。我认为\path
实际上不会浪费时间绘图,这会提高效率。不确定如何做到这一点,甚至不知道它是否会提高效率。