使用 Matplotlib 进行交互式数据可视化

PythonPythonBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在数据可视化中,放大图表的特定区域对于更好地理解和分析数据非常有用。Matplotlib 是一个广受欢迎的 Python 数据可视化库,它提供了一种方法来创建两个相同的面板,并在右侧面板中放大,以在第一个面板中显示一个矩形,表示缩放区域。在本实验中,我们将学习如何在 Matplotlib 中创建此交互式缩放功能。

虚拟机使用提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签,以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,请随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。

导入必要的库

我们首先将导入必要的库,包括 Matplotlib 和 NumPy。

import matplotlib.pyplot as plt
import numpy as np

from matplotlib.patches import Rectangle

创建 UpdatingRect 类

我们将创建一个名为 UpdatingRect 的 Rectangle 子类。调用这个类时会传入一个 Axes 实例,使矩形更新其形状以匹配 Axes 的边界。

class UpdatingRect(Rectangle):
    def __call__(self, ax):
        self.set_bounds(*ax.viewLim.bounds)
        ax.figure.canvas.draw_idle()

创建 MandelbrotDisplay 类

我们将创建一个名为 MandelbrotDisplay 的类,它会在我们放大时重新生成一个分形集,以便我们能够实际看到不断增加的细节。左侧面板中的一个框将显示我们所放大的区域。

class MandelbrotDisplay:
    def __init__(self, h=500, w=500, niter=50, radius=2., power=2):
        self.height = h
        self.width = w
        self.niter = niter
        self.radius = radius
        self.power = power

    def compute_image(self, xstart, xend, ystart, yend):
        self.x = np.linspace(xstart, xend, self.width)
        self.y = np.linspace(ystart, yend, self.height).reshape(-1, 1)
        c = self.x + 1.0j * self.y
        threshold_time = np.zeros((self.height, self.width))
        z = np.zeros(threshold_time.shape, dtype=complex)
        mask = np.ones(threshold_time.shape, dtype=bool)
        for i in range(self.niter):
            z[mask] = z[mask]**self.power + c[mask]
            mask = (np.abs(z) < self.radius)
            threshold_time += mask
        return threshold_time

    def ax_update(self, ax):
        ax.set_autoscale_on(False)
        self.width, self.height = \
            np.round(ax.patch.get_window_extent().size).astype(int)
        vl = ax.viewLim
        extent = vl.x0, vl.x1, vl.y0, vl.y1
        im = ax.images[-1]
        im.set_data(self.compute_image(*extent))
        im.set_extent(extent)
        ax.figure.canvas.draw_idle()

创建图表

我们将通过以下步骤创建图表:首先使用 MandelbrotDisplay 类计算图像,然后使用 subplots 创建两个相同的面板。我们将使用 imshow 把图像添加到两个面板中,并将 UpdatingRect 对象添加到左侧面板。

md = MandelbrotDisplay()
Z = md.compute_image(-2., 0.5, -1.25, 1.25)

fig1, (ax1, ax2) = plt.subplots(1, 2)
ax1.imshow(Z, origin='lower',
           extent=(md.x.min(), md.x.max(), md.y.min(), md.y.max()))
ax2.imshow(Z, origin='lower',
           extent=(md.x.min(), md.x.max(), md.y.min(), md.y.max()))

rect = UpdatingRect(
    [0, 0], 0, 0, facecolor='none', edgecolor='black', linewidth=1.0)
rect.set_bounds(*ax2.viewLim.bounds)
ax1.add_patch(rect)

添加缩放功能

我们将通过把 xlim_changedylim_changed 事件连接到 UpdatingRectMandelbrotDisplay 对象来添加缩放功能。

ax2.callbacks.connect('xlim_changed', rect)
ax2.callbacks.connect('ylim_changed', rect)

ax2.callbacks.connect('xlim_changed', md.ax_update)
ax2.callbacks.connect('ylim_changed', md.ax_update)
ax2.set_title("Zoom here")

显示图表

我们将使用 show() 函数来显示图表。

plt.show()

总结

在本实验中,我们学习了如何使用两个相同的面板以及 UpdatingRect 和 MandelbrotDisplay 类在 Matplotlib 中创建交互式缩放功能。通过添加缩放功能,我们能够更好地理解和分析图表中的数据。