Reputation: 129
I have two lines:
y=3x-4
y=-x+5
They intersect and form 4 regions in space (see image below).
Mathematically, the regions can be determined with the following inequations:
Region1: y<3x-4 & y>-x+5
Region2: y>3x-4 & y>-x+5
Region3: y>3x-4 & y<-x+5
Region4: y<3x-4 & y<-x+5
I want to fill all of those regions independently. However when I try to use plt.fill_between
I can only get regions 1 and/or 3. How can I fill regions 2 and 4 using matplotlib and fill_between?
The code that I tried for region 3 is the following (source):
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,6,0.1)
y = np.arange(0,6,0.1)
# The lines to plot
y1 = 3*x - 4
y2 = -x+5
# The upper edge of polygon (min of lines y1 & y2)
y3 = np.minimum(y1, y2)
# Set y-limit, making neg y-values not show in plot
plt.ylim(0, 6)
plt.xlim(0, 6)
# Plotting of lines
plt.plot(x, y1,
x, y2)
# Filling between (region 3)
plt.fill_between(x, y2, y3, color='grey', alpha=0.5)
plt.show()
Upvotes: 1
Views: 443
Reputation: 3559
It's because you have set the limits incorrectly. Setting them as 2 horizontal lines, 6
and 0
, does the trick. Note that I have changed the step of arange
because, to have a neat picture, the intersection point (2.25 in your case) needs to belong to x
range
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,6,0.05)
# The lines to plot
y1 = 3*x - 4
y2 = -x+5
# Set y-limit, making neg y-values not show in plot
plt.ylim(0, 6)
plt.xlim(0, 6)
# Filling between (region 3)
plt.fill_between(x, np.maximum(y1, y2), [6] * len(x), color='grey', alpha=0.5)
plt.fill_between(x, np.minimum(y1, y2), [0] * len(x), color='cyan', alpha=0.5)
plt.show()
Upvotes: 2
Reputation: 2534
The trick here is to define a new polygon based on the intersections of the lines, and use $y(x) = 0$ as your bottom border.
The implementation of this requires the following code. First we externally calculate and hardcode the intersection points between the lines and the a-axis:
# calculate intersections between lines and x axis
intersect_x = 9/4
y1_0 = 4/3
y2_0 = 5
Once we have those stored, we go through every x value. If the x value is greater than our starting point (where the climbing curve crosses the x-axis) but less than the intersection point, we add the climbing curve point at that x value. If the x-value is greater than the intersection point but less than the end point (where the falling curve crosses the x-axis), we add the falling curve point at that x value. At each step, we add a y=0 point to a new list to be our floor for the fill-in operation.
# here we manually perform the operation you were trying to do
# with np.minimum; we also add an (x, 0) point for
# every point we add to our new polygon
new_x = []
new_y = []
bottom_y = []
for x_dx, xx in enumerate(x):
if xx > y1_0 and xx < intersect_x:
new_x.append(xx)
new_y.append(y1[x_dx])
bottom_y.append(0)
elif xx < y2_0 and xx > intersect_x:
new_x.append(xx)
new_y.append(y2[x_dx])
bottom_y.append(0)
Now we just replace our fill_between
code with the new curves:
plt.fill_between(new_x, new_y, bottom_y, color='grey', alpha=0.5)
This is the full code:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,6,0.1)
y = np.arange(0,6,0.1)
# The lines to plot
y1 = 3*x - 4
y2 = -x+5
# calculate intersections between lines and x axis
intersect_x = 9/4
y1_0 = 4/3
y2_0 = 5
# here we manually perform the operation you were trying to do
# with np.minimum; we also add an (x, 0) point for
# every point we add to our new polygon
new_x = []
new_y = []
bottom_y = []
for x_dx, xx in enumerate(x):
if xx > y1_0 and xx < intersect_x:
new_x.append(xx)
new_y.append(y1[x_dx])
bottom_y.append(0)
elif xx < y2_0 and xx > intersect_x:
new_x.append(xx)
new_y.append(y2[x_dx])
bottom_y.append(0)
# The upper edge of polygon (min of lines y1 & y2)
y3 = np.minimum(y1, y2)
# Set y-limit, making neg y-values not show in plot
plt.ylim(0, 6)
plt.xlim(0, 6)
# Plotting of lines
plt.plot(x, y1,
x, y2)
# Filling between (region 3)
plt.fill_between(new_x, new_y, bottom_y, color='grey', alpha=0.5)
plt.show()
And this is the result:
Happy coding!
Upvotes: 1