查找在matplotlib中绘制的两条曲线之间的区域(fill_between区域) [英] Find the area between two curves plotted in matplotlib (fill_between area)

查看:725
本文介绍了查找在matplotlib中绘制的两条曲线之间的区域(fill_between区域)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个曲线的x和y值的列表,它们都具有怪异的形状,而我没有任何函数.我需要做两件事:(1)将其绘制并阴影化曲线之间的区域,如下图所示; (2)找出曲线之间此阴影区域的总面积.

I have a list of x and y values for two curves, both having weird shapes, and I don't have a function for any of them. I need to do two things: (1) plot it and shade the area between the curves like the image below; (2) find the total area of this shaded region between the curves.

我能够使用matplotlib中的fill_between和fill_betweenx绘制和绘制这些曲线之间的区域,但是我不知道如何计算它们之间的确切区域,特别是因为我没有任何函数这些曲线.

I'm able to plot and shade the area between those curves with fill_between and fill_betweenx in matplotlib, but I have no idea on how to calculate the exact area between them, specially because I don't have a function for any of those curves.

有什么想法吗?

我到处都是,找不到一个简单的解决方案.我非常绝望,因此非常感谢您的帮助.

I looked everywhere and can't find a simple solution for this. I'm quite desperate, so any help is much appreciated.

非常感谢!

供以后参考(以防有人遇到相同的问题),这是我如何解决此问题的方法(几个月后):将每条曲线的第一个和最后一个节点/点连接在一起,产生一个大的奇怪形状的多边形,然后使用 shapely 自动计算多边形的面积,是曲线之间的确切区域,无论它们走的方式或非线性如何.就像魅力一样,已经运行了数千条曲线. :)

For future reference (in case somebody runs into the same problem), here is how I solved this (many months later): connected the first and last node/point of each curve together, resulting in a big weird-shaped polygon, then used shapely to calculate the polygon's area automatically, which is the exact area between the curves, no matter which way they go or how nonlinear they are. Works like a charm, ran for thousands of curves already. :)

这是我的代码:

from shapely.geometry import Polygon

x_y_curve1 = [(0.121,0.232),(2.898,4.554),(7.865,9.987)] #these are your points for curve 1 (I just put some random numbers)
x_y_curve2 = [(1.221,1.232),(3.898,5.554),(8.865,7.987)] #these are your points for curve 2 (I just put some random numbers)

polygon_points = [] #creates a empty list where we will append the points to create the polygon

for xyvalue in x_y_curve1:
    polygon_points.append([xyvalue[0],xyvalue[1]]) #append all xy points for curve 1

for xyvalue in x_y_curve2[::-1]:
    polygon_points.append([xyvalue[0],xyvalue[1]]) #append all xy points for curve 2 in the reverse order (from last point to first point)

for xyvalue in x_y_curve1[0:1]:
    polygon_points.append([xyvalue[0],xyvalue[1]]) #append the first point in curve 1 again, to it "closes" the polygon

polygon = Polygon(polygon_points)
area = polygon.area
print(area)

推荐答案

在两条曲线不相交的块中,面积计算很简单:就是上面指出的梯形.如果它们相交,那么您将在x [i]和x [i + 1]之间创建两个三角形,并且应将两个区域相加.如果要直接执行此操作,则应分别处理这两种情况.这是解决您的问题的基本工作示例.首先,我将从一些虚假数据开始:

The area calculation is straightforward in blocks where the two curves don't intersect: thats the trapezium as has been pointed out above. If they intersect, then you create two triangles between x[i] and x[i+1], and you should add the area of the two. If you want to do it directly, you should handle the two cases separately. Here's a basic working example to solve your problem. First, I will start with some fake data:

#!/usr/bin/python
import numpy as np

# let us generate fake test data
x = np.arange(10)
y1 = np.random.rand(10) * 20
y2 = np.random.rand(10) * 20

现在,主要代码.根据您的绘图,看起来您在相同的X点上定义了y1和y2.然后我们定义,

Now, the main code. Based on your plot, looks like you have y1 and y2 defined at the same X points. Then we define,

z = y1-y2
dx = x[1:] - x[:-1]
cross_test = np.sign(z[:-1] * z[1:])

每当两个图交叉时,

cross_test将为负.在这些点上,我们要计算交叉的x坐标.为简单起见,我将计算y的所有线段的交点的x坐标.对于两条曲线不相交的地方,它们将是无用的值,我们不会在任何地方使用它们.这样只会使代码更易于理解.

cross_test will be negative whenever the two graphs cross. At these points, we want to calculate the x coordinate of the crossover. For simplicity, I will calculate x coordinates of the intersection of all segments of y. For places where the two curves don't intersect, they will be useless values, and we won't use them anywhere. This just keeps the code easier to understand.

假设您在x1和x2处分别有z1和z2,那么我们求解x0使得z = 0:

Suppose you have z1 and z2 at x1 and x2, then we are solving for x0 such that z = 0:

# (z2 - z1)/(x2 - x1) = (z0 - z1) / (x0 - x1) = -z1/(x0 - x1)
# x0 = x1 - (x2 - x1) / (z2 - z1) * z1
x_intersect = x[:-1] - dx / (z[1:] - z[:-1]) * z[:-1]
dx_intersect = - dx / (z[1:] - z[:-1]) * z[:-1]

在曲线不相交的地方,面积可以简单地由下式给出:

Where the curves don't intersect, area is simply given by:

areas_pos = abs(z[:-1] + z[1:]) * 0.5 * dx # signs of both z are same

在它们相交的地方,我们添加了两个三角形的区域:

Where they intersect, we add areas of both triangles:

areas_neg = 0.5 * dx_intersect * abs(z[:-1]) + 0.5 * (dx - dx_intersect) * abs(z[1:])

现在,要选择每个块x [i]到x [i + 1]中的区域,为此我使用np.where:

Now, the area in each block x[i] to x[i+1] is to be selected, for which I use np.where:

areas = np.where(cross_test < 0, areas_neg, areas_pos)
total_area = np.sum(areas)

这是您想要的答案.如上所述,如果两个y图都定义在不同的x点,则将变得更加复杂.如果要测试,只需绘制即可(在我的测试案例中,y范围为-20到20)

That is your desired answer. As has been pointed out above, this will get more complicated if the both the y graphs were defined at different x points. If you want to test this, you can simply plot it (in my test case, y range will be -20 to 20)

negatives = np.where(cross_test < 0)
positives = np.where(cross_test >= 0)
plot(x, y1)
plot(x, y2)
plot(x, z)
plt.vlines(x_intersect[negatives], -20, 20)

这篇关于查找在matplotlib中绘制的两条曲线之间的区域(fill_between区域)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆