I would like to fill between 3 lines in matplotlib.pyplot but unfortunately the fill_between gives me opportunity to fill between only two lines. Any ideas how to deal with this?
Edit:
Ok, I did not explain what I really mean since I cannot add the picture with my current reputation so maybe in that way:
I try to fill the polygon bounded by these lines and I have no idea how because fill_between gives me opportunity to fill only area between two of them. Below the fill equation:
y <= 4- 2x
y <= 3 - 1/2x
y <= 1 - x
y >= 0
x >= 0
the x and y bigger than 0 is obvious. I start the plot from (0,0) but I still have 3 lines...
y <= 4- 2x
y <= 3 - 1/2x
y <= 1 - x
If you start the plot in point (0, 0), and therefore do not need to consider the area of the polygon not in the first quadrant, then this should do the trick in this particular situation:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,10,0.1)
# The lines to plot
y1 = 4 - 2*x
y2 = 3 - 0.5*x
y3 = 1 -x
# The upper edge of polygon (min of lines y1 & y2)
y4 = np.minimum(y1, y2)
# Set y-limit, making neg y-values not show in plot
plt.ylim(0, 5)
# Plotting of lines
plt.plot(x, y1,
x, y2,
x, y3)
# Filling between line y3 and line y4
plt.fill_between(x, y3, y4, color='grey', alpha='0.5')
plt.show()
To use fill_between, specify the X values first, than the two Y sets that you want to "fill between". An example is show below:
import pylab as plt
import numpy as np
X = np.linspace(0,3,200)
Y1 = X**2 + 3
Y2 = np.exp(X) + 2
Y3 = np.cos(X)
plt.plot(X,Y1,lw=4)
plt.plot(X,Y2,lw=4)
plt.plot(X,Y3,lw=4)
plt.fill_between(X, Y1,Y2,color='k',alpha=.5)
plt.fill_between(X, Y1,Y3,color='y',alpha=.5)
plt.show()
If, instead, you only wanted to fill between Y2 and Y3:
plt.fill_between(X, Y2,Y3,color='m',alpha=.5)
this would give you
Just compute the corner points of the polygon, i.e., the points where the lines intersect.
Then plot the polygon using pyplot.fill.
Example:
import matplotlib.pyplot as plt
# define corner points
x = [1,2,1,0]
y = [2,1,0,1]
# plot
plt.fill(x,y)
plt.show()
resulting Image:
Related
I have charts like this:
I need to draw these graphs in python so that later I can evenly distribute the points inside this curve. I tried to implement like this, but it's far from what I need:
import matplotlib.pyplot as plt
X = range(0,3)
y = [x*x for x in X]
z = [2-x for x in X]
plt.plot(X, y, color='r', label='x^2')
plt.plot(X, z, color='g', label='2-x')
plt.xlabel("X")
plt.ylabel("Y")
plt.legend()
plt.show()
Two remarks:
The lines you get are "overlaying" since you share the same x. However, in your desired output, the x of the square function extends from 0 to 1 and the x of the linear function extends from 1 to 2.
You get only three connected points, because range() only returns discrete integer values. numpy.linspace() returns evenly spaced numbers over a specified interval.
As #tdy mentioned in the comment, you should create two different x's for each curve:
x1 = np.linspace(0, 1)
x2 = np.linspace(1, 2)
Then you calculate the function values:
y1 = x1 ** 2
y2 = 2 - x2
Then you plot both:
plt.plot(x1, y1)
plt.plot(x2, y2)
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()
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()
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!
In essence, I need to make a square scatterplot from (0,1) to (0,1). The points within the quarter-circle centered at the origin need to be colored red, and the ones outside need to be colored blue. The way I was planning to do it was to make 2 scatterplots on the same graph, one with y1 = the range under the quarter-circle, and one with y2 = the range above the quarter-circle.
This is what I have so far:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.random(500)
y1 < np.sqrt(1-x**2)
y2 > np.sqrt(1-x**2)
plt.xlim(0, 1)
plt.ylim(0, 1)
c1 = 'r'
c2 = 'b'
plt.scatter(x, y1, c=c1, cmap=plt.cm.jet)
plt.scatter(x, y2, c=c2, cmap=plt.cm.jet)
plt.axes().set_aspect(1)
plt.show()
This code gives me this plot, when I should be getting something like this. If someone could tell me how to fix my y1 and y2 values, I'd appreciate it. Thank you!
If you have a closer look at
y1 < np.sqrt(1-x**2)
y2 > np.sqrt(1-x**2)
... these two lines only give you boolean arrays. The code you posted actually gives you an error, which makes clear, you never saved y1 and y2.
So you rather should:
x = np.random.random(500)
y = np.sqrt(1-np.random.random(500)**2)
x1 = x[y<x]
y1 = y[y<x]
...
PS: adapted, now x and y are not directly correlated any more, corresponding to comments
IMO your approach doesn't quite get the point of the (assumed) topic. Afaics this is about calculating pi by the ratio of randomly distributed points in a (quarter) circle and its square.
The point is here to not calculate the points coordinates in any way, but to let them be distributed completely randomly. And afterwards, you can go and decide to plot this in whatever color you want with whatever underlying rule or algorithm.
Short, this would be my approach:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.random(500)
y = np.random.random(500)
plt.xlim(0, 1)
plt.ylim(0, 1)
c = np.where(x**2 + y**2 < 1, 'r', 'b')
plt.scatter(x, y, c=c)
plt.gca().set_aspect(1)
plt.show()
for completeness an example of the assumed topic:
for i in range(1,9):
x = np.random.random(10**i)
y = np.random.random(10**i)
d = np.where(x**2 + y**2 < 1, 1, 0)
print(f'{10**i:>9} points: {4*np.sum(d)/d.size}')
# 10 points: 2.8
# 100 points: 3.08
# 1000 points: 3.076
# 10000 points: 3.1556
# 100000 points: 3.14456
# 1000000 points: 3.141884
# 10000000 points: 3.142634
# 100000000 points: 3.14158668
I am using the below python codes so as to generate an animated plot for the variable shift point.Here x1 is the shift point which has to be shifted rightwards so as to get plot as shown in the figure below.Here the point x1 is not moving beyond 3 and I am getting in plot window one after another.I need all the plot in one single window.Is there any other method?Could any one help me in this?
Please also refer the link below
How do you plot a line with two slopes using python
from matplotlib import pyplot as plt
import time
import numpy as np
def ShiftPoint(i):
x1=0;
while x1 < i:
m0 = 1
m1 = 0.15
x0 = 0 # Initial x value
#x1 = 5 # Point to be shifted [Shift Point]
x2 = 10
y0 = 0
y1 = y0 + m0 * (x1 - x0)
y2 = y1 + m1 * (x2 - x1)
plt.plot([x0, x1, x2],[y0, y1, y2])
plt.grid()
plt.show()
plt.hold()
time.sleep(0.25)
x1 += 1
I would like to fill between 3 lines in matplotlib.pyplot but unfortunately the fill_between gives me opportunity to fill between only two lines. Any ideas how to deal with this?
Edit:
Ok, I did not explain what I really mean since I cannot add the picture with my current reputation so maybe in that way:
I try to fill the polygon bounded by these lines and I have no idea how because fill_between gives me opportunity to fill only area between two of them. Below the fill equation:
y <= 4- 2x
y <= 3 - 1/2x
y <= 1 - x
y >= 0
x >= 0
the x and y bigger than 0 is obvious. I start the plot from (0,0) but I still have 3 lines...
y <= 4- 2x
y <= 3 - 1/2x
y <= 1 - x
If you start the plot in point (0, 0), and therefore do not need to consider the area of the polygon not in the first quadrant, then this should do the trick in this particular situation:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,10,0.1)
# The lines to plot
y1 = 4 - 2*x
y2 = 3 - 0.5*x
y3 = 1 -x
# The upper edge of polygon (min of lines y1 & y2)
y4 = np.minimum(y1, y2)
# Set y-limit, making neg y-values not show in plot
plt.ylim(0, 5)
# Plotting of lines
plt.plot(x, y1,
x, y2,
x, y3)
# Filling between line y3 and line y4
plt.fill_between(x, y3, y4, color='grey', alpha='0.5')
plt.show()
To use fill_between, specify the X values first, than the two Y sets that you want to "fill between". An example is show below:
import pylab as plt
import numpy as np
X = np.linspace(0,3,200)
Y1 = X**2 + 3
Y2 = np.exp(X) + 2
Y3 = np.cos(X)
plt.plot(X,Y1,lw=4)
plt.plot(X,Y2,lw=4)
plt.plot(X,Y3,lw=4)
plt.fill_between(X, Y1,Y2,color='k',alpha=.5)
plt.fill_between(X, Y1,Y3,color='y',alpha=.5)
plt.show()
If, instead, you only wanted to fill between Y2 and Y3:
plt.fill_between(X, Y2,Y3,color='m',alpha=.5)
this would give you
Just compute the corner points of the polygon, i.e., the points where the lines intersect.
Then plot the polygon using pyplot.fill.
Example:
import matplotlib.pyplot as plt
# define corner points
x = [1,2,1,0]
y = [2,1,0,1]
# plot
plt.fill(x,y)
plt.show()
resulting Image: