This question already has an answer here:
How to fill space to border with in Matplotlib [duplicate]
(1 answer)
Closed 2 years ago.
I need to fill the area between y1 and y but but I don't understand how to limit the area under y2
import numpy as np
import matplotlib.pyplot as plt
y = lambda z: (4 * z - z ** 2) ** (1 / 2)
y1 = lambda x: (8 * x - x ** 2) ** (1 / 2)
y2 = lambda c: c * 3 ** (1 / 2)
x = np.linspace(0, 12, 500)
z = np.linspace(0, 12, 500)
c = np.linspace(0, 12, 500)
plt.ylim(0, 4)
plt.xlim(0, 4)
plt.plot(z, y(z), color='blue', label="$y=\\sqrt{4x-x^2}$")
plt.plot(c, y2(c), color='black', label='$y=x\\sqrt{3}$')
plt.plot(x, y1(x), color='red', label='$y=\\sqrt{8x-x^2}$')
plt.plot([0, 4], [0, 0], color='yellow', label='y=0')
plt.grid(True, zorder=5)
plt.fill_between(x, y(z), y1(x), where=(y2(c) >= y1(x)), alpha=0.5)
plt.legend()
plt.show()
Do you want to fill between the minimum of y1, y2 and y?
miny = np.minimum(y2(x),y1(x))
plt.fill_between(x, y(x), miny, where=(miny>=y(x)), alpha=0.5)
plt.legend()
plt.show()
Output:
Related
I have created this topic before: How to Add another subplot to show Solid of Revolution toward x-axis?
I want to plot the solid from a curve 3 + 2x - x^2 that is revolved about:
a. the x-axis
b. the y-axis
c. the line y = -1
d. the line x = 4
this is my MWE (the problem is to find the inverse of 3 + 2x - x^2 is not something easy thus I have no idea how to make this code works):
# Compare the plot at xy axis with the solid of revolution toward x and y axis
# For function x=(y)^(3/2)
import matplotlib.pyplot as plt
import numpy as np
n = 100
fig = plt.figure(figsize=(14, 7))
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222, projection='3d')
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224, projection='3d')
y = np.linspace(0, 9, n)
x = (y) ** (3 / 2)
t = np.linspace(0, np.pi * 2, n)
xn = np.outer(x, np.cos(t))
yn = np.outer(x, np.sin(t))
zn = np.zeros_like(xn)
for i in range(len(x)):
zn[i:i + 1, :] = np.full_like(zn[0, :], y[i])
ax1.plot(x, y)
ax1.set_title("$f(x)$")
ax2.plot_surface(xn, yn, zn)
ax2.set_title("$f(x)$: Revolution around $y$")
# find the inverse of the function
x_inverse = y
y_inverse = np.power(x_inverse, 3 / 2)
xn_inverse = np.outer(x_inverse, np.cos(t))
yn_inverse = np.outer(x_inverse, np.sin(t))
zn_inverse = np.zeros_like(xn_inverse)
for i in range(len(x_inverse)):
zn_inverse[i:i + 1, :] = np.full_like(zn_inverse[0, :], y_inverse[i])
ax3.plot(x_inverse, y_inverse)
ax3.set_title("Inverse of $f(x)$")
ax4.plot_surface(xn_inverse, yn_inverse, zn_inverse)
ax4.set_title("$f(x)$: Revolution around $x$")
plt.tight_layout()
plt.show()
I have this code modified from the topic here:
How to produce a revolution of a 2D plot with matplotlib in Python
The plot contains a subplot in the XY plane and another subplot of the solid of revolution toward the y-axis.
I want to add another subplot that is the solid of revolution toward the x-axis + how to add a legend to each subplot (above them), so there will be 3 subplots.
This is my MWE:
# Compare the plot at xy axis with the solid of revolution
# For function x=(y-2)^(1/3)
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
n = 100
fig = plt.figure(figsize=(12,6))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122,projection='3d')
y = np.linspace(np.pi/8, np.pi*40/5, n)
x = (y-2)**(1/3) # x = np.sin(y)
t = np.linspace(0, np.pi*2, n)
xn = np.outer(x, np.cos(t))
yn = np.outer(x, np.sin(t))
zn = np.zeros_like(xn)
for i in range(len(x)):
zn[i:i+1,:] = np.full_like(zn[0,:], y[i])
ax1.plot(x, y)
ax2.plot_surface(xn, yn, zn)
plt.show()
Option 1:
Simply reverse x and y to switch the axes of the function.
x = np.linspace(np.pi/8, np.pi*40/5, n)
y = (x-2)**(1/3)
Option 2:
It is a little complicated. You can also accomplish this by finding the inverse of the original function.
The inverse of f(x) = y = x^3 + 2 is f^{-1}(y) = (y - 2)^(1/3).
I modified the code you provided.
import matplotlib.pyplot as plt
import numpy as np
n = 100
fig = plt.figure(figsize=(14, 7))
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222, projection='3d')
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224, projection='3d')
y = np.linspace(np.pi / 8, np.pi * 40 / 5, n)
x = (y - 2) ** (1 / 3)
t = np.linspace(0, np.pi * 2, n)
xn = np.outer(x, np.cos(t))
yn = np.outer(x, np.sin(t))
zn = np.zeros_like(xn)
for i in range(len(x)):
zn[i:i + 1, :] = np.full_like(zn[0, :], y[i])
ax1.plot(x, y)
ax1.set_title("$f(x)$")
ax2.plot_surface(xn, yn, zn)
ax2.set_title("$f(x)$: Revolution around $y$")
# find the inverse of the function
x_inverse = y
y_inverse = np.power(x_inverse - 2, 1 / 3)
xn_inverse = np.outer(x_inverse, np.cos(t))
yn_inverse = np.outer(x_inverse, np.sin(t))
zn_inverse = np.zeros_like(xn_inverse)
for i in range(len(x_inverse)):
zn_inverse[i:i + 1, :] = np.full_like(zn_inverse[0, :], y_inverse[i])
ax3.plot(x_inverse, y_inverse)
ax3.set_title("Inverse of $f(x)$")
ax4.plot_surface(xn_inverse, yn_inverse, zn_inverse)
ax4.set_title("$f(x)$: Revolution around $x$")
plt.tight_layout()
plt.show()
I want to fill between 3 lines in the following problem. Here's the code:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# Construct lines
# x > 0
x = np.linspace(0, 20, 2000)
# C1
y1 = (36-2*x)/6
# C2
y2 = (30-5*x)/3
# C3
y3 = (40-8*x)/2
# C4
# y4 = 0*x
# Make plot
plt.plot(x, y1, label=r'$2 x_{1} + 6 x_{2}\leq 36$')
plt.plot(x, y2, label=r'$x_{1} + 3 x_{2}\leq 30$')
plt.plot(x, y3, label=r'$x_{1} + 2 x_{2}\leq 40$')
# plt.plot(x, y4, label=r'$x_{1}, x_{2}\geq 0$')
plt.xlim((0, 16))
plt.ylim((0, 11))
plt.xlabel(r'$x_1$')
plt.ylabel(r'$x_2$')
# Fill feasible region
y5 = np.minimum(0, 0)
y6 = np.maximum(y2, y3)
plt.fill_between(x, y1, y2, color='grey', alpha=0.5,
interpolate=True)
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
I'd like to fill what is hatched in red in the image below (between y1, y2, y3, and zero)
You could fill between zero and the minimum of the three curves:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 20, 2000)
y1 = (36 - 2 * x) / 6
y2 = (30 - 5 * x) / 3
y3 = (40 - 8 * x) / 2
plt.plot(x, y1, label=r'$2 x_{1} + 6 x_{2}\leq 36$')
plt.plot(x, y2, label=r'$x_{1} + 3 x_{2}\leq 30$')
plt.plot(x, y3, label=r'$x_{1} + 2 x_{2}\leq 40$')
plt.xlim((0, 16))
plt.ylim((0, 11))
plt.xlabel(r'$x_1$')
plt.ylabel(r'$x_2$')
plt.fill_between(x, y1, y2, color='grey', alpha=0.5,
interpolate=True)
plt.fill_between(x, 0, np.min([y1, y2, y3], axis=0), color='red', alpha=0.5, hatch='//',
interpolate=True, label='$intersection$')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.tight_layout()
plt.show()
Note that:
np.vstack([y1, y2, y3]) creates a 3-row array from your 3 "y" arrays.
….min(0) computes minimum along each column, so it is actually
a minimum of your 3 source arrays (also with negative values for higher x).
….clip(min=0) transforms the above negative elements to 0.
So add to your code:
plt.fill_between(x, 0, np.vstack([y1, y2, y3]).min(0).clip(min=0),
color='yellow', alpha=0.5, interpolate=True)
e.g. after your first fill_between.
For your data, and code with the above instruction added, I got:
If you want, change the filling color to whatever suits your needs.
I'm having some trouble using the TeX "\tanh" expression in my matplotlib chart legend. The reason is that "\t" is also the reserved symbol in Python used for tabs. Hence my expression doesn't show properly. How can I make this work?
This is my code
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-10, 10, 1000)
y1 = np.e ** x / (np.e ** x + 1)
y2 = (np.e ** (2 * x) - 1) / (np.e ** (2 * x) + 1)
plt.figure(figsize=(6, 6 / 16 * 9))
ax = plt.gca()
ax.plot(x, y1, color=(0, 101/255, 189/255), linewidth=2, label='$\sigma(x)$')
ax.plot(x, y2, color=(227/255, 114/255, 34/255), linewidth=2, label='$\tanh(x)$')
ax.set_ylim(-1, 1)
ax.set_xlim(-6, 6)
ax.grid(True, which='both', ls='-')
plt.legend()
plt.show()
This is the (wrong) outcome
I believe you need to use a raw-string to ignore the \t, so label=r'$\tanh(x)$'.
This question already has answers here:
How to plot in multiple subplots
(12 answers)
Closed 1 year ago.
I am trying to loop subplot for n rows 2 columns for Gaussian function as shown in following example code. This returns histogram and normal distribution, I tried a couple of methods unsuccessfully, any help is most appreciated.
Speed = [0,10,20,30,40]
Torque1 = []
Torque2 = []
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque1.append(Trq)
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque2.append(Trq)
def gaussian_Histo(s, Title):
mu, sigma = np.mean(s), np.std(s, ddof=1) # mean and standard deviation
fig = plt.figure(Title, figsize=(10, 6), dpi=80)
count, bins, ignored = plt.hist(s, 80, normed=True)
plt.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) ), linewidth=2, color='r')
plt.grid(True)
plt.title(Title)
plt.show()
def main():
nrows = 3
fig, axes = plt.subplots(nrows, 2)
for row in axes:
# for i in range(3):
x = gaussian_Histo(Torque1[i], 'Torque at'+str(Speed[i])+'RPM')
y = gaussian_Histo(Torque2[i], 'Torque at'+str(Speed[i])+'RPM')
plot(row, x, y)
plt.show()
def plot(axrow, x, y):
axrow[0].plot(x, color='red')
axrow[1].plot(y, color='green')
main()
The reason you are seeing that error is because you are not returning any value from gaussian_Histo and are therefore trying to plot x = None.
I have removed the part of the code that plots each histogram individually as this will interrupt the plotting of your grid, unless you change the way you are creating that figure. As a result I have used np.histogram rather than plt.hist (plt.hist actually uses np.histogram behind the scenes)
Example:
Speed = [0,10,20,30,40]
Torque1 = []
Torque2 = []
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque1.append(Trq)
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque2.append(Trq)
def gaussian_Histo(s, Title):
mu, sigma = np.mean(s), np.std(s, ddof=1) # mean and standard deviation
count, bins = np.histogram(s, 80, normed=True)
test = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) )
return test
def main():
nrows = 3
fig, axes = plt.subplots(nrows, 2)
for row in axes:
x = gaussian_Histo(Torque1[i], 'Torque at'+str(Speed[i])+'RPM')
y = gaussian_Histo(Torque2[i], 'Torque at'+str(Speed[i])+'RPM')
plot(row, x, y)
plt.show()
def plot(axrow, x, y):
axrow[0].plot(x, color='red')
axrow[1].plot(y, color='green')
main()
This produces the figure:
I came up with code which plots histogram individually. I modified my plotting function (gaussian_Histo) which returns individual plot.
Speed = [0,10,20,30,40]
Torque1 = []
Torque2 = []
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque1.append(Trq)
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque2.append(Trq)
# print(Torque1)
def gaussian_Histo(s, Title, ax = None):
mu, sigma = np.mean(s), np.std(s, ddof=1) # mean and standard deviation
if ax is None:
ax = plt.gca()
count, bins, ignored = ax.hist(s, 80, normed=True)
ax.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) ), linewidth=2, color='r')
ax.grid(True)
ax.set_title(Title)
plt.show()
for i in range(len(Speed)):
f, (ax1, ax2) = plt.subplots(1, 2, sharey=False, figsize=(8,6), dpi=50)
gaussian_Histo(Torque1[i], 'Torque1 at '+str(Speed[i])+'RPM', ax1)
gaussian_Histo(Torque2[i], 'Torque2 at '+str(Speed[i])+'RPM', ax2)
Individual Plot Results in this link