PGFPlots - 填充两条曲线之间的区域

PGFPlots - 填充两条曲线之间的区域

三天前我在 Stack Exchange 上发布了一个关于如何填充两条曲线之间的区域的问题(查看问题)我的目标是填充区域为两条曲线颜色不同基于何时其中一个高于另一个。关键是结果持续的。这意味着,当图 1(目标)高于图 2(基准)时,下面的区域应该始终是绿色的。但当地块 2 高于地块 1 时,下面的面积应该始终是红色的。我从 esdd 和 Ross 那里得到了两个很好的解决方案。但是,当曲线和曲线背景变得更加复杂时,这两种方法都不够用。

下面您可以按相应的顺序找到:

  1. 我正在处理的情节的截图
  2. 平均能量损失
  3. 解释为什么这两种解决方案都很好,但对于这个图来说并不是最优的。

解决方案包含在 MWE 中(并被注释)。

截屏: 在此处输入图片描述

梅威瑟:

\documentclass{article}
\usepackage{pgfplots}
\usepgfplotslibrary{fillbetween}
\pgfplotsset{compat=newest}
\pgfplotstableread[col sep=semicolon,trim cells]{
    index;value;bins;benchmark_hoeveelheid;benchmark_cumulatief;target_hoeveelheid;target_cumulatief;
    1;30;1-30;1;1;0;0;
    2;60;31-60;1;3;0;0;
    3;90;61-90;2;5;0;0;
    4;120;91-120;4;9;7;7;
    5;150;121-150;4;13;29;36;
    6;180;151-180;6;19;0;36;
    7;210;181-210;4;23;7;43;
    8;240;211-240;6;29;0;43;
    9;270;241-270;4;32;0;43;
    10;300;271-300;5;37;0;43;
    11;330;301-330;3;40;0;43;
    12;360;331-360;5;45;7;50;
    13;390;361-390;4;49;14;64;
    14;420;391-420;4;53;0;64;
    15;450;421-450;5;57;7;71;
    16;480;451-480;4;61;0;71;
    17;510;481-510;3;65;7;79;
    18;540;511-540;3;68;0;79;
    19;570;541-570;3;70;0;79;
    20;600;571-600;2;73;0;79;
    21;630;601-630;3;76;0;79;
    22;660;631-660;3;79;0;79;
    23;690;661-690;2;81;0;79;
    24;720;691-720;2;84;0;79;
    25;750;721-750;2;86;0;79;
    26;780;751-780;2;88;0;79;
    27;810;781-810;0;88;0;79;
    28;840;811-840;1;89;0;79;
    29;870;841-870;0;90;0;79;
    30;900;871-900;0;90;7;86;
    31;930;901-930;1;91;7;93;
    32;960;931-960;0;91;0;93;
    33;990;961-990;0;92;0;93;
    34;1020;991-1020;1;93;0;93;
    35;1050;1021-1050;1;93;0;93;
    36;1080;1051-1080;0;94;0;93;
    37;1110;1081-1110;0;94;7;100;
    38;1140;1111-1140;0;95;0;100;
}\data


\begin{document}
\begin{figure}[h]
    \begin{tikzpicture}[trim axis left]
    \begin{axis}[
    x tick label style={
        /pgf/number format/1000 sep=},
    scale only axis,
    height=10cm,
    width=\textwidth,
    ymin=0,
    every node near coord/.append style={font=\tiny, inner sep=1pt},
    xtick=data,
    xticklabels from table={\data}{value},
    %xticklabel={\euro\pgfmathprintnumber\tick},
    xticklabel style={rotate=45},
    xticklabel style={font=\tiny},
    yticklabel={\pgfmathparse{\tick*1}\pgfmathprintnumber{\pgfmathresult}\%},
    yticklabel style={font=\scriptsize},
    ymajorgrids,
    xmajorgrids,
    bar width=0.1cm,
    enlarge x limits=0.01,
    enlarge y limits={value=0.05,upper},
    legend style={at={(0.5,-0.07)},
        anchor=north,legend columns=-1},
    ]

    \addplot[name path=plot1,draw=green!60!black,thick,sharp plot]
    table [x=index, y=target_cumulatief] {\data};
    \addplot[name path=plot2,draw=blue!70!pink,thick,sharp plot]
    table [x=index, y=benchmark_cumulatief] {\data};

%   SOLUTION 1
%   
%     \path[name path=xaxis](current axis.south west)--(current axis.south east);
%     \addplot[fill opacity=0.2, green] fill between[ 
%     of = plot1 and plot2,
%     split
%     ];
%     \addplot[fill opacity=1, white] fill between[of = plot1 and xaxis];

%   SOLUTION 2
%     \addplot
%     fill between[of = plot1 and plot2,
%     split,
%     every segment no 0/.style={fill=green, fill opacity=0.2},
%     every segment no 1/.style={fill=red, fill opacity=0.2},  
%     every segment no 2/.style={fill=green, fill opacity=0.2},
%     every segment no 3/.style={fill=red, fill opacity=0.2},
%     every segment no 4/.style={fill=green, fill opacity=0.2},
%     every segment no 5/.style={fill=red, fill opacity=0.2},
%     every segment no 6/.style={fill=green, fill opacity=0.2},
%     every segment no 7/.style={fill=red, fill opacity=0.2},
%     ];
    \legend{{Target},{Benchmark}}
    \end{axis}
    \end{tikzpicture}
\end{figure}
\end{document}

解决方案 1:

在此处输入图片描述

第一个解决方案使用 x 轴和两条曲线之间的差异来为下方区域着色。这意味着,虽然当图 1 高于图 2 时可以为曲线下方区域着色,但反之则不行。此外,网格会被白色遮挡。

解决方案 2:

在此处输入图片描述

这个解决方案越来越接近我想要的,但缺乏一致性。你必须指定你想要的不同部分的颜色,这意味着它不会自动遵循我预先定义的规则“plot 1>plot2 = green”和“plot2>plot1 = red”。

我知道我可能听起来很挑剔,但这对我来说非常重要,因为我必须 100% 正确。如果我要绘制大量此类图表,这些示例根本不够,因为我必须手动调整所有图表。

希望有人能根据这些细节帮助我。另外,我想提一下问题+解决方案,因为我认为findintersections这里创建的命令可能是最佳解决方案。但是,在这种情况下它不起作用,因为您需要一个常数和一条曲线,而我使用的是两条曲线。尽管如此,如果可以调整它,它就会起作用。

答案1

您可以填充图层中的区域axis background。然后它们的填充位于网格后面。

也许可以使用略有不同的颜色进行填充。然后,您可以用一种颜色填充曲线之间的区域,然后将其中一条曲线和 x 轴之间的区域填充为白色。在最后一步中,您可以使用不透明度用第二种颜色为曲线之间的区域着色。

在此处输入图片描述

代码:

\documentclass{article}
\usepackage{pgfplots}
\usepgfplotslibrary{fillbetween}
\pgfplotsset{compat=newest}
\pgfplotstableread[col sep=semicolon,trim cells]{
    index;value;bins;benchmark_hoeveelheid;benchmark_cumulatief;target_hoeveelheid;target_cumulatief;
    1;30;1-30;1;1;0;0;
    2;60;31-60;1;3;0;0;
    3;90;61-90;2;5;0;0;
    4;120;91-120;4;9;7;7;
    5;150;121-150;4;13;29;36;
    6;180;151-180;6;19;0;36;
    7;210;181-210;4;23;7;43;
    8;240;211-240;6;29;0;43;
    9;270;241-270;4;32;0;43;
    10;300;271-300;5;37;0;43;
    11;330;301-330;3;40;0;43;
    12;360;331-360;5;45;7;50;
    13;390;361-390;4;49;14;64;
    14;420;391-420;4;53;0;64;
    15;450;421-450;5;57;7;71;
    16;480;451-480;4;61;0;71;
    17;510;481-510;3;65;7;79;
    18;540;511-540;3;68;0;79;
    19;570;541-570;3;70;0;79;
    20;600;571-600;2;73;0;79;
    21;630;601-630;3;76;0;79;
    22;660;631-660;3;79;0;79;
    23;690;661-690;2;81;0;79;
    24;720;691-720;2;84;0;79;
    25;750;721-750;2;86;0;79;
    26;780;751-780;2;88;0;79;
    27;810;781-810;0;88;0;79;
    28;840;811-840;1;89;0;79;
    29;870;841-870;0;90;0;79;
    30;900;871-900;0;90;7;86;
    31;930;901-930;1;91;7;93;
    32;960;931-960;0;91;0;93;
    33;990;961-990;0;92;0;93;
    34;1020;991-1020;1;93;0;93;
    35;1050;1021-1050;1;93;0;93;
    36;1080;1051-1080;0;94;0;93;
    37;1110;1081-1110;0;94;7;100;
    38;1140;1111-1140;0;95;0;100;
}\data


\begin{document}
\begin{figure}[h]
    \begin{tikzpicture}[trim axis left,
    fill between/on layer=axis background% <- filling behind the grid
    ]
    \begin{axis}[
    x tick label style={
        /pgf/number format/1000 sep=},
    scale only axis,
    height=10cm,
    width=\textwidth,
    ymin=0,
    every node near coord/.append style={font=\tiny, inner sep=1pt},
    xtick=data,
    xticklabels from table={\data}{value},
    %xticklabel={\euro\pgfmathprintnumber\tick},
    xticklabel style={rotate=45},
    xticklabel style={font=\tiny},
    yticklabel={\pgfmathparse{\tick*1}\pgfmathprintnumber{\pgfmathresult}\%},
    yticklabel style={font=\scriptsize},
    ymajorgrids,
    xmajorgrids,
    bar width=0.1cm,
    enlarge x limits=0.01,
    enlarge y limits={value=0.05,upper},
    legend style={at={(0.5,-0.07)},
        anchor=north,legend columns=-1},
    ]

    \addplot[name path=plot1,draw=green!60!black,thick,sharp plot]
    table [x=index, y=target_cumulatief] {\data};
    \addplot[name path=plot2,draw=blue!70!pink,thick,sharp plot]
    table [x=index, y=benchmark_cumulatief] {\data};

       \path[name path=xaxis](current axis.south west)--(current axis.south east);
       \addplot[green!30] fill between[ 
       of = plot1 and plot2,
       split
       ];
       \addplot[white] fill between[of = plot1 and xaxis];
       \addplot[red!70!yellow,fill opacity=.2] fill between[ 
       of = plot1 and plot2,
       split
       ];

    \legend{{Target},{Benchmark}}
    \end{axis}
    \end{tikzpicture}
\end{figure}
\end{document}

相关内容