\begingroup

我知道有很多关于这个问题的帖子,但我就是找不到解决我的问题的正确帖子。问题是我有两个数据集,我使用它们来绘制它们ListLinePlot。我想用不同的颜色填充它们包围的区域(当 A 位于 B 上时使用绿色,当 B 位于 A 上时使用黄色)。但这个简单的问题却很有挑战性。无论我如何使用命令,它对Filling区域使用的颜色始终相同(见照片)。我知道一种方法是找到交点然后重新生成数据,但我不想弄乱它。我相信应该有一个简单的解决方法。

其次,如何分别计算这两个面积?

以下是代码:

test1 = {{0.01, 21.96}, {0.19, 22.06}, {0.36, 22.06}, {0.54, 
    22.06}, {0.71, 22.06}, {0.89, 22.06}, {1.06, 22.05}, {1.24, 
    22.05}, {1.41, 22.06}, {1.59, 22.05}, {1.76, 22.05}, {1.94, 
    22.05}, {2.11, 22.05}, {2.29, 22.05}, {2.46, 22.06}, {2.64, 
    22.04}, {2.81, 22.03}, {2.99, 21.96}, {3.16, 21.79}, {3.34, 
    20.56}, {3.51, 16.5}, {3.69, 11.71}, {3.86, 7.62}, {4.04, 
    4.52}, {4.21, 3.19}, {4.39, 2.99}, {4.56, 2.95}, {4.74, 
    2.95}, {4.91, 2.95}, {5.09, 2.95}, {5.26, 2.96}, {5.44, 
    2.96}, {5.61, 2.96}, {5.79, 2.96}, {5.96, 2.96}, {6.14, 2.96}};

test2 = {{0.02, 22.16}, {0.08, 22.14}, {0.16, 22.07}, {0.22, 
    22.07}, {0.29, 22.07}, {0.36, 22.07}, {0.44, 22.06}, {0.5, 
    22.06}, {0.58, 22.06}, {0.64, 22.06}, {0.72, 22.06}, {0.78, 
    22.06}, {0.86, 22.06}, {0.92, 22.06}, {1., 22.06}, {1.06, 
    22.06}, {1.14, 22.06}, {1.2, 22.06}, {1.27, 22.06}, {1.34, 
    22.06}, {1.41, 22.06}, {1.48, 22.06}, {1.56, 22.06}, {1.62, 
    22.06}, {1.69, 22.06}, {1.76, 22.06}, {1.84, 22.06}, {1.9, 22.06},
    {1.97, 22.06}, {2.04, 22.06}, {2.11, 22.06}, {2.18, 22.06}, {2.25,
     22.06}, {2.32, 22.06}, {2.4, 22.06}, {2.46, 22.06}, {2.54, 
    22.06}, {2.6, 22.06}, {2.68, 22.06}, {2.74, 22.05}, {2.82, 
    22.05}, {2.88, 22.04}, {2.96, 22.02}, {3.02, 22.}, {3.09, 
    21.97}, {3.16, 21.92}, {3.24, 21.83}, {3.3, 21.73}, {3.38, 
    21.59}, {3.44, 21.34}, {3.52, 20.82}, {3.58, 17.72}, {3.66, 
    12.82}, {3.72, 9.42}, {3.8, 6.91}, {3.86, 5.12}, {3.94, 
    4.05}, {4., 3.51}, {4.08, 3.25}, {4.14, 3.13}, {4.22, 
    3.06}, {4.28, 3.02}, {4.36, 3.}, {4.42, 2.99}, {4.5, 2.99}, {4.57,
     2.99}, {4.63, 2.99}, {4.7, 2.99}, {4.78, 2.99}, {4.84, 
    2.99}, {4.92, 2.99}, {4.98, 2.99}, {5.05, 2.99}, {5.12, 
    2.99}, {5.2, 2.99}, {5.26, 2.99}, {5.34, 2.99}, {5.4, 
    2.99}, {5.48, 2.99}, {5.54, 2.99}, {5.62, 2.99}, {5.68, 
    2.99}, {5.76, 2.99}, {5.82, 2.99}, {5.9, 2.99}, {5.96, 
    2.99}, {6.04, 2.99}, {6.1, 2.99}, {6.18, 2.99}, {6.24, 2.99}};

ListLinePlot[{test1, test2}, Filling -> {1 -> {{2}, {Yellow, Green}}}]

谢谢

\endgroup

2

  • \begingroup
    这些Filling命令似乎有用,我想我输入的和你输入的完全一样?抱歉,我真的不知道如何确定是什么导致了Filling这里的行为
    \endgroup


    – 

  • \begingroup
    @ydd 请查看已编辑的帖子。
    \endgroup


    – 


最佳答案
3

\begingroup

看起来这些点需要位于相同的 x 值。

我首先创建线性插值并选择两个插值的域内的 x 值:

int1 = Interpolation[test1, InterpolationOrder -> 1];
int2 = Interpolation[test2, InterpolationOrder -> 1];

xPoints = Union[test1[[All, 1]], test2[[All, 1]]];

(*select points that are in the range of both interpolations*)
domains = Interval[#["Domain"][[1]]] & /@ {int1, int2};
range = IntervalIntersection @@ domains;
xPoints = Select[xPoints, IntervalMemberQ[range, #] &];

然后评估这些点的插值:

p1 = {#, int1[#]} & /@ xPoints;
p2 = {#, int2[#]} & /@ xPoints;
ListLinePlot[{p1, p2}, Filling -> {1 -> {{2}, {Yellow, Green}}}]

然后使用Clip我定义两个仅当int2 > int1int1 > int2时才为非零的函数。我绘制了这些截断函数的绝对值来显示这种行为:

(*define diff to be the difference between the interpolations*)
diff[x_] = int1[x] - int2[x];
(*when int2>int1,diff is negative*)
yellowReg[x_] := Clip[diff[x], {-Infinity, 0}]
(*when int1>int2,diff is positive*)
greenReg[x_] := Clip[diff[x], {0, Infinity}];

Plot[{Abs@yellowReg[x], Abs@greenReg[x]}, {x, xPoints[[1]], 
  xPoints[[-1]]}, Filling -> Axis, PlotStyle -> {Yellow, Green}, 
 FillingStyle -> Opacity[1], PlotRange -> All]

现在我们可以找到这两个区域的大小:

(*calculate magnitude of yellow and green regions*)
yellowArea = 
 NIntegrate[yellowReg[x], {x, xPoints[[1]], xPoints[[-1]]}] // Abs

greenArea = 
 NIntegrate[greenReg[x], {x, xPoints[[1]], xPoints[[-1]]}] // Abs

(*1.12331*)

(*0.814679*)

请注意,黄色区域还包括左侧的小区域int2 > int1。如果您不想包括该区域,可以将下积分边界更改xPoints[[1]]为更大的区域,但仍然包括大黄色区域。

\endgroup

1

  • \begingroup
    我喜欢你的回答。它提供的信息比我预期的要多。
    \endgroup


    – 

\begingroup

  • 两条线相交多次,不完全只有一个交点。我们可以通过以下方式看到这一点:
polys = PolygonDecomposition[Polygon[Join[Reverse@test1, test2]]];
n = Length[polys]
colors = {Yellow, Blue, Green, Brown, Red, Blue, Cyan};
mapping = Association[Thread[colors -> polys]]
Graphics[Thread[{colors, polys}], AspectRatio -> 1]

  • 所以你想要红色和绿色多边形的面积。
{Area[mapping@Red], Area[mapping@Green]}

{1.03459, 0.814679}

\endgroup

1

  • \begingroup
    完美答案!谢谢
    \endgroup


    – 

\begingroup

由于你一开始没有给出任何数据,所以我随意制作了一些数据:

dat1 = Table[{x, -ArcTan[10 x]}, {x, -21, 21}] // N;
dat2 = Table[{x, -ArcTan[2 x]}, {x, -20, 20}] // N;
dat2 = Join[{dat1[[1]]}, dat2, {dat1[[-1]]}]

现在我们可以绘制这些数据了。以下是选项“填充”的格式,它将执行您想要的操作:

ListLinePlot[{dat1, dat2},  Filling -> {1 -> {{2}, {Blue, Red}}}]

要获得曲线之间两部分的面积,首先要通过点定义一个插值函数,然后进行积分:

f1 = Interpolation[dat1];
f2 = Interpolation[dat2];
NIntegrate[f1[x] - f2[x], {x, -21, 0}]

1.42858

-NIntegrate[f1[x] - f2[x], {x, 0, 21}]

1.42858

\endgroup

2

  • \begingroup
    谢谢你的回答。我的命令中已经有了这个填充选项,但是没有用。
    \endgroup


    – 

  • \begingroup
    我认为它不起作用的原因是 x 参数不一样。如果这是真的,您可以在“Plot”命令中使用插值函数,而不是使用“ListLinePlot”
    \endgroup


    –