
Tenho várias curvas/conjuntos de dados (obtidos em simulações de Monte Carlo) com erros y dependentes de x que gostaria de traçar com os erros indicados de alguma forma. Como cada curva consiste em um grande número de pontos de dados com erros bastante pequenos, usar barras de erro comuns não parece ser a solução mais informativa/estética. Em vez disso, acho que seria melhor indicar o erro pela espessura da linha (local) (ou espessura na direção y). Isso poderia, por exemplo, ser feito plotando y(x)+dy(x) e y(x)-dy(x) e preenchendo entre as duas curvas. Mas como fazer isso (de uma maneira razoavelmente fácil - lembre-se: tenho várias curvas!) em Pgfplots?
Minha pergunta talvez seja um pouco semelhante aEste, mas não sei como fazer as manipulações de tabela (dentro do Pgfplots) necessárias no meu caso.
Aqui está um exemplo simplificado da aparência dos meus arquivos de dados:
x y dy
0 2 0.1
1 4 0.5
2 3 0.2
3 3 0.3
Responder1
Você pode usar gráficos empilhados para desenhar as bandas de incerteza antes de traçar a linha de dados real. Primeiro você diria \addplot table [y expr=\thisrow{<data col>}-\thisrow{<error col}] {<datatable>};
para determinar o limite inferior e depois
\addplot [fill=<colour>] table [y expr=2*\thisrow{<error col}] {<datatable>} \closedcycle;
preencher a área entre o limite inferior e superior.
Esses dois \addplot
comandos podem ser agrupados em uma macro para gerar os gráficos, como segue:
\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};
}
você pode gerar um gráfico com uma banda de erro usando
\errorband[<plot options>]{<data file>}{<x column>}{<y column>}{<error column>}
Abaixo está um exemplo traçando oExtensão média do gelo marinho do norte e do sul.
Fetterer, F., K. Knowles, W. Meier, M. Savoie e AK Windnagel. 2017, atualizado diariamente. Índice de Gelo Marinho, Versão 3. [Dados/Norte+Sul/Mês]. Boulder, Colorado, EUA. NSIDC: Centro Nacional de Dados de Neve e Gelo. faça: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}
ATUALIZAR
Os dados atualmente disponíveis cobrem a extensão média do gelo marinho de 1981 a 2010. Para reprodutibilidade, o código LaTeX pode ser atualizado da seguinte forma (excluindo os gráficos lineares NH e 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};
Responder2
Você pode usar um mesh
gráfico com line width
. No entanto, isso causa transições irregulares de um segmento de linha para o próximo. Mas talvez seja viável:
caso você tenha conjuntos de dados menores, os marcadores podem ocultar as transições:
Aqui está o código:
\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 ideia principal é que (a) um mesh
gráfico desenha segmentos de linha individuais e (b) \pgfplotspointmetatransformed
contém os point meta
dados de uma forma totalmente normalizada: a menor entrada de metadados (0,1 aqui) obtém \pgfplotspointmetatransformed=0
e a maior (0,5 aqui) obtém \pgfplotspointmetatransformed=1000
. Os valores intermediários são interpolados linearmente. Conseqüentemente, podemos usá-los com segurança line width
conforme acima.
Observe que as opções são avaliadas em contextos onde esta meta macro de ponto não está disponível. Para este fim, defini-o como 1000 globalmente (o que deve ser adequado para estes contextos).
Responder3
Ultimamente tenho brincado com a fillbetween
biblioteca e pensei que seria ideal para este cenário.
A resposta é inspirada na resposta de Jake acima, mas usa a fillbetween
biblioteca introduzida na pgfplots
versão 1.10 em vez de gráficos empilhados.
Saída:
A errorband
macro leva seis argumentos obrigatórios: nome da tabela de dados, coluna x, coluna y, coluna de erro, linha e cor da banda de erro e opacidade da banda de erro.
Ele funciona criando gráficos auxiliares invisíveis para os limites superior e inferior do erro e nomeando-os para uso pela fillbetween
biblioteca. fillbetween
usa os argumentos de cor e opacidade como configurações de faixa de erro. Finalmente, ele plota a coluna y no topo da banda de erro usando a cor fornecida.
Os gráficos auxiliares e fillbetween
os gráficos de banda de erro são esquecidos e não são incluídos na legenda. Isso facilita o uso errorband
imediatamente seguido \addlegendentry
(ou \legend
no final) para gerar uma legenda.
(Dados não mostrados.)
Solução:
\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}
Considerações de desempenho:
Para aqueles que ainda estão lendo, presumo que traçar os gráficos invisíveis apenas para nomeá-los torna isso menos eficiente do que poderia ser. Se alguém souber uma maneira de substituir isso:
\addplot [name path=pluserror,draw=none,no markers,forget plot]
table [x={#2},y expr=\thisrow{#3}+\thisrow{#4}] {\datatable};
com algo como:
\path[name path=pluserror] table [x={#2},y expr=\thisrow{#3}+\thisrow{#4}] {\datatable};
seria ótimo. Presumo \path
que não perca tempo desenhando, o que o tornaria mais eficiente. Não tenho certeza de como fazer isso ou mesmo se isso melhoraria a eficiência.