使用 Matplotlib 重采样数据

Beginner

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

简介

在本实验中,我们将学习如何使用 Python 中的 Matplotlib 对数据进行下采样。下采样是降低信号采样率或样本大小的过程。我们将使用一个类来对数据进行下采样,并在缩放时重新计算。

虚拟机使用提示

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

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

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

导入库

我们将从导入必要的库开始。在这个任务中,我们将使用 Matplotlib 和 NumPy 库。

import matplotlib.pyplot as plt
import numpy as np

定义类

我们将定义一个名为 DataDisplayDownsampler 的类,该类将对数据进行下采样,并在缩放时重新计算。该类的构造函数将把 xdata 和 ydata 作为输入参数。我们将把最大点数设置为 50,并计算 xdata 的差值。

class DataDisplayDownsampler:
    def __init__(self, xdata, ydata):
        self.origYData = ydata
        self.origXData = xdata
        self.max_points = 50
        self.delta = xdata[-1] - xdata[0]

对数据进行下采样

我们将定义一个 downsample 方法来对数据进行下采样。该方法将把 xstart 和 xend 作为输入参数。我们会获取视图范围内的点,并将掩码扩展一位,以捕捉视图范围外的点,从而避免截断线条。我们将计算需要舍弃多少个点并对数据进行掩码处理。最后,我们会对数据进行下采样并返回 xdata 和 ydata。

def downsample(self, xstart, xend):
    ## get the points in the view range
    mask = (self.origXData > xstart) & (self.origXData < xend)
    ## dilate the mask by one to catch the points just outside
    ## of the view range to not truncate the line
    mask = np.convolve([1, 1, 1], mask, mode='same').astype(bool)
    ## sort out how many points to drop
    ratio = max(np.sum(mask) // self.max_points, 1)

    ## mask data
    xdata = self.origXData[mask]
    ydata = self.origYData[mask]

    ## downsample data
    xdata = xdata[::ratio]
    ydata = ydata[::ratio]

    print(f"using {len(ydata)} of {np.sum(mask)} visible points")

    return xdata, ydata

更新数据

我们将定义一个 update 方法来更新数据。该方法将把 ax(坐标轴)作为输入参数。我们会通过获取视图限制并检查视图限制的宽度是否与差值不同来更新线条。如果视图限制的宽度与差值不同,我们将更新差值并获取 xstart 和 xend。然后我们会将数据设置为下采样后的数据并绘制空闲状态。

def update(self, ax):
    ## Update the line
    lims = ax.viewLim
    if abs(lims.width - self.delta) > 1e-8:
        self.delta = lims.width
        xstart, xend = lims.intervalx
        self.line.set_data(*self.downsample(xstart, xend))
        ax.figure.canvas.draw_idle()

创建信号

我们将使用 NumPy 创建一个信号。我们将使用 linspace 函数创建一个数组 xdata,其起始值为 16,终止值为 365,元素数量为 (365 - 16) * 4。我们将使用 sin 和 cos 函数创建一个数组 ydata。

xdata = np.linspace(16, 365, (365-16)*4)
ydata = np.sin(2*np.pi*xdata/153) + np.cos(2*np.pi*xdata/127)

创建绘图

我们将使用 Matplotlib 创建一个绘图。我们将使用 xdata 和 ydata 创建 DataDisplayDownsampler 类的一个实例 d。我们将使用 subplots 函数创建一个图形和一个坐标轴。我们将连接线条并将自动缩放设置为 False。我们将连接以更改视图限制,设置 x 轴限制并显示绘图。

d = DataDisplayDownsampler(xdata, ydata)
fig, ax = plt.subplots()
d.line, = ax.plot(xdata, ydata, 'o-')
ax.set_autoscale_on(False)
ax.callbacks.connect('xlim_changed', d.update)
ax.set_xlim(16, 365)
plt.show()

总结

在这个实验中,我们学习了如何使用 Python 中的 Matplotlib 对数据进行下采样。我们使用了一个对数据进行下采样并在缩放时重新计算的类。我们使用 NumPy 创建了一个信号,并使用 Matplotlib 创建了一个绘图。我们连接以更改视图限制并设置了 x 轴限制。