Matplotlib 可视化之多图层叠加

本文介绍了如何使用Python的Matplotlib库进行曲线绘制和颜色填充。首先定义了生成随机曲线的函数,然后通过设置不同参数绘制出多条曲线并填充颜色,展示了fill_between函数的多种用法,如基本填充、置信区间、选择性填充和整个轴的填充。文章还强调了zorder属性在多图层叠加中的作用,以确保正确显示曲线层次。最后,通过循环绘制了多个图形实例,进一步阐述了曲线可视化的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们一起来看看精彩的可视化图表是如何绘制出来的。

定义曲线函数

首先定义出图中随机曲线的绘图函数。

# Some nice but random curves
def curve():
    n = np.random.randint(1, 5)
    centers = np.random.normal(0.0, 1.0, n)
    widths = np.random.uniform(5.0, 50.0, n)
    widths = 10 * widths / widths.sum()
    scales = np.random.uniform(0.1, 1.0, n)
    scales /= scales.sum()
    X = np.zeros(500)
    x = np.linspace(-3, 3, len(X))
    for center, width, scale in zip(centers, widths, scales):
        X = X + scale * np.exp(-(x - center) * (x - center) * width)
    return X

绘图

将比较抽象的曲线函数可视化,更加直观。

np.random.seed(123)
# 获取曲线数据
Y = curve()
X = np.linspace(-3, 3, len(Y))
# 画布准备
fig = plt.figure(figsize=(10, 6),dpi=600)
# 设置画布
ax = plt.subplot(1, 1, 1, frameon=False, sharex=ax)
# 绘制曲线
ax.plot(X, 3 * Y, color="k", 
        linewidth=0.75, zorder=100)
plt.show()
3e5e2be49fda706c00e4986a5e531f9a.png

由于该函数的随机性,每次运行都会给出不同的结果:

89d769bbc26badd9bf82842ab3c4c6ea.gif

配置样式

填充颜色、设置坐标轴及坐标轴标签。这里重点是颜色填充函数:Axes.fill_between()

Axes.fill_between(self, x, y1, y2=0, where=None, 
                  interpolate=False, step=None, 
                  *, data=None, **kwargs)

参数:

  • x: 该参数包含用于定义曲线的数据点的水平坐标。

  • y1: 此参数包含用于定义第一条曲线的数据点的y坐标

  • y2: 该参数包含用于定义第二条曲线的数据点的y坐标。它是可选的,默认值为0。

  • where: 此参数是可选参数。它用于排除某些水平区域的填充。

  • interpolate: 此参数也是可选参数。它是错误栏行的线宽,默认值为NONE。

  • step: 此参数也是可选参数。它用于定义填充是否应为阶跃函数。

颜色填充有四种用法

① 基本用法

参数 y1y2 可以是标量,表示给定y值处的水平边界。只要 y1 给出, y2  默认为0。

ax1.fill_between(X, Y, color=color[0])
ax2.fill_between(X, Y, 1, color=color[1])
ax3.fill_between(X, Y, Y2, color=color[2])
ebdbdfadcc41e31c446f1263f780c6ca.png
② 置信区间

一个常见的应用 fill_between 是置信带的指示。

fill_between 使用填充颜色填充某个区域时,这些颜色可能有点强,以至于宣兵夺主。我们希望淡化填充区域而突出主体。因此设置参数alpha的值,以达到减淡颜色,使该区域半透明的目的。

y_err = X.std() * np.sqrt(1/len(X) +  (X - X.mean())**2 / np.sum((X - X.mean())**2))
ax.fill_between(X, 3*Y - y_err, 3*Y + y_err,
                alpha=0.2, color=cmap(0.3))
62b7652d06d0d4f1a600daa04a987c7d.png
③ 选择性填充水平区域

参数where允许指定要填充的 x 范围。它是一个与x大小相同的布尔数组。

仅填充连续 True 序列的x范围。因此,相邻的 TrueFalse 值之间的范围永远不会被填满。当数据点应该表示一个连续的量时,通常不希望出现这种情况。因此,建议设置 interpolate=True,除非数据点的x距离足够细,使上述效果不明显。插值近似于实际的x位置,在那里 where 条件将改变,并扩展填充到那里。

ax1.fill_between(x01, y01, y02, where=(y01 > y02), color='C0', alpha=0.3)
ax1.fill_between(x01, y01, y02,where=(y01 < y02), color='C1', alpha=0.3)

ax2.fill_between(x01, y01, y02, where=(y01 > y02), color='C0', alpha=0.3,
                 interpolate=True)
ax2.fill_between(x01, y01, y02, where=(y01 <= y02), color='C1', alpha=0.3,
                 interpolate=True)
963848f4398719dad22308689e227c33.png
④ 在整个轴上有选择地标记水平区域

同样的选择机制可以应用于填满坐标轴的全部垂直高度。为了不受y极限的影响,我们添加了一个转换来解释数据坐标中的x值和坐标轴坐标中的y值。

下面的示例标记y数据高于给定阈值的区域。

threshold = 0.4
ax.axhline(threshold, color=cmap(0.2), 
           lw=2, alpha=0.7,linestyle='-.')
ax.fill_between(X, 0, 1, where= 3*Y > threshold, 
                color=cmap(0.5), 
                alpha=0.5, 
                transform=ax.get_xaxis_transform())
24f6c9f90f8146db2b1ddd33a7efcec5.png
本案例中,选择第一种常规填充。
# 画布准备
cmap = mpl.cm.get_cmap("Spectral")
color = cmap(0)
ax.fill_between(X, 3 * Y, 0, color=color, zorder=100)
ax.yaxis.set_tick_params(tick1On=False)
ax.set_xlim(-3, 3)
ax.set_ylim(-1, 4)
ax.axvline(0.0, ls="--", lw=0.75, color="black", zorder=250)
ax.text(
    0.0, 1.0,
    "Value %d" % 1,
    ha="left", va="top",
    weight="bold", size=15,
    transform=ax.transAxes,)
ax.yaxis.set_tick_params(labelleft=True)
ax.set_yticks(np.arange(1))
ax.set_yticklabels(["Serie %d" % i for i in range(1, 2)])
for tick in ax.yaxis.get_major_ticks():
  tick.label.set_fontsize(15)
  tick.label.set_verticalalignment("bottom") # 垂直对齐
plt.show()
4a42698fabef7688e3c08f358bbc444b.png

bfdeae63b7eb901256c20bd41826a1df.gif

多图层叠加

zorder 用来控制绘图顺序,其值越大,画上去越晚,线条的叠加就是在上面的。对 plotting 方法的任何调用都可以显式地为该特定项的 zorder 设置值。许多创建可见对象的函数都接受 zorder 参数。或者可以在绘图后调用 set_order() 函数作用在创建的对象上。

接下来开始绘制开篇的这个图,我们发现每条曲线都部分地覆盖了其他曲线,因此为每条曲线设置适当的zorder是很重要的,这样渲染将独立于绘制顺序。

通过横向及纵向循环绘制多个图形,这里注意设置叠放次序参数zorder,最下面的在最上面,然后依次叠放。

rows, cols = 3, 4
ax = None
for n in range(rows):
   # 设置多子图
  ax = plt.subplot(1, rows, n + 1, frameon=False, sharex=ax)
    for i in range(cols):
       Y = curve()
        X = np.linspace(-3, 3, len(Y))
        ax.plot(X, 3 * Y + i, color="k", linewidth=0.75, zorder=100 - i)
        color = cmap(i / cols)
        ax.fill_between(X, 3 * Y + i, i, color=color, zorder=100 - i)
f9c60b68c10604f65c5c020305fa2706.png

最后多次循环,可以得到下图。

84a29aa8b41722887dffddcb7c56df67.png

参考资料

Scientific Visualisation-Python & Matplotlib
Python数据科学手册

END

 
 

各位伙伴们好,詹帅本帅搭建了一个个人博客和小程序,汇集各种干货和资源,也方便大家阅读,感兴趣的小伙伴请移步小程序体验一下哦!(欢迎提建议)

推荐阅读

牛逼!Python常用数据类型的基本操作(长文系列第①篇)

牛逼!Python的判断、循环和各种表达式(长文系列第②篇)

牛逼!Python函数和文件操作(长文系列第③篇)

牛逼!Python错误、异常和模块(长文系列第④篇)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值