过滤(平滑)连续流数据的最有效方法是什么

What is the most efficient way to filter (smooth) continuous streaming data

我正在制作自己的系统监控工具。我在从设备接收的连续原始数据流上寻找 运行 过滤器(如高斯过滤器或类似过滤器)(在这种情况下是我的 cpu %)。

数据值集合的长度为 n 个元素。每次这段代码 运行s 它都会附加新的 cpu 值并删除最旧的,使集合的长度保持在 n 本质上是 deque([float('nan')] * n, maxlen=n) 其中 n 是我绘制的图表的长度。

然后它通过创建平滑数据点的高斯过滤器过滤整个集合,然后绘制它们,创建类似于大多数系统监视器的动画图 cpu % 在您的计算机上找到的图。

这很好用...但是,必须有一种更有效的方法来过滤传入数据,而不是 运行每次添加新数据 val 时都对整个数据集进行过滤(在我的例子中,图表每 .2 秒更新一次)

我可以想出不过滤整个列表的方法,但我不确定它们是否非常有效。信号处理领域有什么适合我的吗?如果我的解释有点混乱,我很抱歉,我对此很陌生。

from scipy.ndimage.filters import gaussian_filter1d

# Not my actual code but hopefully describes what im doing
def animate():  # function that is called every couple of milliseconds to animate the graph
    # ... other stuff
    values.append(get_new_val) # values = collection of data vals from cpu
    line.set_ydata(gaussian_filter1d(values, sigma=4)) # line = the line object used for graphing 
    # ... other stuff
    graph_line(line)  # function that graphs the line

tl;dr:寻找一种优化的方法来平滑原始流数据,而不是每次都过滤整个数据集。

我从来没有用过,但您需要的听起来像是 Savitzky–Golay filter 的用途。它是一个 local 平滑过滤器,可用于使数据更加可区分(并在我们使用它时区分它)。

好消息是 scipy supports this filter 从 0.14 版开始。文档的相关部分:

scipy.signal.savgol_filter(x, window_length, polyorder, deriv=0, delta=1.0, axis=-1, mode='interp', cval=0.0)

  Apply a Savitzky-Golay filter to an array.
  This is a 1-d filter. If x has dimension greater than 1, axis determines the axis along which the filter is applied.
  Parameters:   

  x : array_like
      The data to be filtered. If x is not a single or double precision floating point array, it will be converted to type numpy.float64 before ftering.
  window_length : int
      The length of the filter window (i.e. the number of coefficients). window_length must be a positive odd integer.
  polyorder : int
      The order of the polynomial used to fit the samples. polyorder must be less than window_length.
  [...]

我会先确定一对小的多项式阶数和 window 大小。您无需使用完整的 n 数据点,只需对长度约为 window_length 的小得多的 deque 进行平滑处理。随着每个新数据点的到来,您必须将其附加到较小的 deque,应用 Savitzky–Golay 过滤器,获取新的过滤点,并将其附加到您的图表。

但是请注意,在我看来,当不在数据集的边缘时,该方法大多定义明确。这可能意味着为了精确起见,您可能必须引入一些测量值的延迟,以便您始终可以使用给定 window 内的点(我的意思是对于给定的时间点,您可能需要 "future" 个数据点才能获得可靠的过滤值)。考虑到您的数据每秒测量五次,如果有必要,这可能是一个合理的折衷方案。