如何突出显示matplotlib中多条曲线中的最低曲线(包络线)
How to highlight the lowest curve (envelope) among multiple curves in matplotlib
假设我有多个数学函数 f1
、f2
、f3
,由 Python 函数表示。我想将它们一起绘制在 [0, 1] 的域上。这是它的样子
import numpy as np
import matplotlib.pyplot as plt
import math
def f1(x):
return 4*x**3 + 9*x**2 + x + 4
def f2(x):
return math.sqrt(x) / (1.01 - x)
def f3(x):
return 30 * math.cos(6 * x)
x = np.arange(0.0, 1.01, 0.01)
for f in [f1, f2, f3]:
vecf = np.vectorize(f)
y = vecf(x)
plt.plot(x, y)
plt.xlim([0, 1])
plt.xlabel(r'$x$')
plt.ylabel(r'$f(x)$')
plt.show()
但是,我想使用 alpha = 1
突出显示所有最低的曲线段(即包络线),同时对曲线的其他部分使用 alpha = 0.5
。我想保留每条曲线的颜色。预期的情节看起来像这样:
谁能建议如何在 matplotlib 中实现这一点?
我尝试按照我在评论中的建议进行操作(“只绘制所有曲线,然后计算一个系列,该系列实际上是其他组合中的最小值,并绘制它,但具有 100% 透明线条颜色并将其上方的整个区域用部分不透明的白色着色。”),我认为它非常接近您的需要:
import numpy as np
import matplotlib.pyplot as plt
import math
def f1(x):
return 4*x**3 + 9*x**2 + x + 4
def f2(x):
return math.sqrt(x) / (1.01 - x)
def f3(x):
return 30 * math.cos(6 * x)
x = np.arange(0.0, 1.01, 0.01)
# initialise min_y to all infinite, there is probably a more efficient way to do this
min_y = np.inf * np.ones(x.shape)
for f in [f1, f2, f3]:
vecf = np.vectorize(f)
y = vecf(x)
# zorder=0 to push curves below plane
plt.plot(x, y, zorder=0)
# compute min_y as we go
min_y = np.minimum(y, min_y)
# what you need, although the +1 is a bit arbitrary
# you may want to add some amount relative to the plt.ylim()
plt.fill_between(x, min_y+1, plt.ylim()[1], color='white', alpha=.5)
plt.xlim([0, 1])
plt.xlabel(r'$x$')
plt.ylabel(r'$f(x)$')
plt.show()
结果:
从你的例子来看,也许你想要一个更像 .7 左右的 alpha。
偷偷摸摸的后续问题,也使线条变得粗壮:
import numpy as np
import matplotlib.pyplot as plt
import math
def f1(x):
return 4*x**3 + 9*x**2 + x + 4
def f2(x):
return math.sqrt(x) / (1.01 - x)
def f3(x):
return 30 * math.cos(6 * x)
x = np.arange(0.0, 1.01, 0.01)
# initialise min_y to all infinite, there is probably a more efficient way to do this
min_y = np.inf * np.ones(x.shape)
plotted = []
for f in [f1, f2, f3]:
vecf = np.vectorize(f)
y = vecf(x)
# zorder=0 to push curves below plane
p = plt.plot(x, y, zorder=0)
# compute min_y as we go
min_y = np.minimum(y, min_y)
# keep the plotted data, to reuse when plotting fat lines
plotted.append((y, p[0].get_color()))
for y, c in plotted:
plt.plot(x, np.ma.masked_where(y > min_y, y), color=c, zorder=1, linewidth=3)
# what you need, although the +1 is a bit arbitrary - you may want to add some amount relative to the plt.ylim()
plt.fill_between(x, min_y+1, plt.ylim()[1], color='white', alpha=.7)
plt.xlim([0, 1])
plt.xlabel(r'$x$')
plt.ylabel(r'$f(x)$')
plt.show()
结果:
假设我有多个数学函数 f1
、f2
、f3
,由 Python 函数表示。我想将它们一起绘制在 [0, 1] 的域上。这是它的样子
import numpy as np
import matplotlib.pyplot as plt
import math
def f1(x):
return 4*x**3 + 9*x**2 + x + 4
def f2(x):
return math.sqrt(x) / (1.01 - x)
def f3(x):
return 30 * math.cos(6 * x)
x = np.arange(0.0, 1.01, 0.01)
for f in [f1, f2, f3]:
vecf = np.vectorize(f)
y = vecf(x)
plt.plot(x, y)
plt.xlim([0, 1])
plt.xlabel(r'$x$')
plt.ylabel(r'$f(x)$')
plt.show()
但是,我想使用 alpha = 1
突出显示所有最低的曲线段(即包络线),同时对曲线的其他部分使用 alpha = 0.5
。我想保留每条曲线的颜色。预期的情节看起来像这样:
谁能建议如何在 matplotlib 中实现这一点?
我尝试按照我在评论中的建议进行操作(“只绘制所有曲线,然后计算一个系列,该系列实际上是其他组合中的最小值,并绘制它,但具有 100% 透明线条颜色并将其上方的整个区域用部分不透明的白色着色。”),我认为它非常接近您的需要:
import numpy as np
import matplotlib.pyplot as plt
import math
def f1(x):
return 4*x**3 + 9*x**2 + x + 4
def f2(x):
return math.sqrt(x) / (1.01 - x)
def f3(x):
return 30 * math.cos(6 * x)
x = np.arange(0.0, 1.01, 0.01)
# initialise min_y to all infinite, there is probably a more efficient way to do this
min_y = np.inf * np.ones(x.shape)
for f in [f1, f2, f3]:
vecf = np.vectorize(f)
y = vecf(x)
# zorder=0 to push curves below plane
plt.plot(x, y, zorder=0)
# compute min_y as we go
min_y = np.minimum(y, min_y)
# what you need, although the +1 is a bit arbitrary
# you may want to add some amount relative to the plt.ylim()
plt.fill_between(x, min_y+1, plt.ylim()[1], color='white', alpha=.5)
plt.xlim([0, 1])
plt.xlabel(r'$x$')
plt.ylabel(r'$f(x)$')
plt.show()
结果:
从你的例子来看,也许你想要一个更像 .7 左右的 alpha。
偷偷摸摸的后续问题,也使线条变得粗壮:
import numpy as np
import matplotlib.pyplot as plt
import math
def f1(x):
return 4*x**3 + 9*x**2 + x + 4
def f2(x):
return math.sqrt(x) / (1.01 - x)
def f3(x):
return 30 * math.cos(6 * x)
x = np.arange(0.0, 1.01, 0.01)
# initialise min_y to all infinite, there is probably a more efficient way to do this
min_y = np.inf * np.ones(x.shape)
plotted = []
for f in [f1, f2, f3]:
vecf = np.vectorize(f)
y = vecf(x)
# zorder=0 to push curves below plane
p = plt.plot(x, y, zorder=0)
# compute min_y as we go
min_y = np.minimum(y, min_y)
# keep the plotted data, to reuse when plotting fat lines
plotted.append((y, p[0].get_color()))
for y, c in plotted:
plt.plot(x, np.ma.masked_where(y > min_y, y), color=c, zorder=1, linewidth=3)
# what you need, although the +1 is a bit arbitrary - you may want to add some amount relative to the plt.ylim()
plt.fill_between(x, min_y+1, plt.ylim()[1], color='white', alpha=.7)
plt.xlim([0, 1])
plt.xlabel(r'$x$')
plt.ylabel(r'$f(x)$')
plt.show()
结果: