如何突出显示matplotlib中多条曲线中的最低曲线(包络线)

How to highlight the lowest curve (envelope) among multiple curves in matplotlib

假设我有多个数学函数 f1f2f3,由 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()

结果: