Find the area between the two curves plotted in matplotlib (fill_between area)

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

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

Any ideas?

I have searched everywhere and cannot find a simple solution for this. I am pretty desperate, so any help is greatly appreciated.

Many thanks!

Area between curves - how to calculate the area of ​​the shaded region without curve's function?


EDIT: In the future (if someone is facing the same problem), here is how I solved it (many months later): connected the first and last node / point of each curve together, the result is a polygon of a large strange shape, then used shapely to automatically calculating the area of ​​the polygon, which is the exact area between the curves, regardless of the direction in which they go or how they are non-linear. It works like a charm, already for thousands of curves. :)

Here is my code:

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) 
+8
python scipy matplotlib area
source share
3 answers

The calculation of the area is simple in blocks where the two curves do not intersect: this is a trapezoid, as mentioned above. If they intersect, then you create two triangles between x [I] and x [g + 1], and you must add the area of ​​two. If you want to do this directly, you must handle the two cases separately. Here is a basic working example to solve your problem. First, I'll 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 

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

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

cross_test will be negative whenever two charts intersect. At these points, we want to calculate the x coordinate of the crossover. For simplicity, I calculate the x coordinates of the intersection of all segments y. For places where the two curves do not intersect, they will be useless values, and we will not use them anywhere. It just makes code easier to understand.

Suppose that z1 and z2 at the point x1 and x2, then we solve for x0 that r = 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] 

If the curves do not intersect, the area is simply set as follows:

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

When 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:]) 

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

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

This is your desired answer. As mentioned above, this will become more complicated if both graphs y were defined at different x points. If you want to verify this, you can simply build it (in my test case, the y range will be from -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) 
+2
source share

Define your two curves as functions of f and g , which are linear in segments, for example. between x1 and x2 , f(x) = f(x1) + ((x-x1)/(x2-x1))*(f(x2)-f(x1)) . Define h(x)=abs(g(x)-f(x)) . Then use scipy.integrate.quad to integrate h.

This way you don't have to worry about intersections. It will perform the "trapezoid summation" suggested by ch41rmn automatically.

+3
source share

Your data set is pretty good in the sense that two data sets have the same x-coordinate set. Therefore, you can calculate the area using a series of trapezoids.

eg. If you define two functions as f (x) and g (x), then between any two consecutive points in x you have four data points:

 (x1, f(x1))-->(x2, f(x2)) (x1, g(x1))-->(x2, g(x2)) 

Then the area of ​​the trapezoid is

 A(x1-->x2) = ( f(x1)-g(x1) + f(x2)-g(x2) ) * (x2-x1)/2 (1) 

A complication arises that equation (1) only works for simply connected regions, i.e. There should be no intersection within this area:

 |\ |\/| |_| vs |/\| 

The area of ​​the two sides of the intersection should be estimated separately. You will need to look at your data to find all the intersection points, and then paste their coordinates into your coordinate list. The correct order x must be maintained. Then you can scroll through the list of simply connected areas and get the sum of the area of ​​the trapezoid.

EDIT:

For curiosity, if the x-coordinates for the two lists are different, you can construct triangles instead. eg.

 .____. | / \ | / \ | / \ |/ \ ._________. 

Avoid overlapping between triangles, so again you will need to find the intersection points and insert them into your ordered list. The length of each side of the triangle can be calculated using the Pythagorean formula, and the area of ​​the triangles can be calculated using the Heron formula.

+2
source share

All Articles