过滤(平滑)连续流数据的最有效方法是什么
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" 个数据点才能获得可靠的过滤值)。考虑到您的数据每秒测量五次,如果有必要,这可能是一个合理的折衷方案。
我正在制作自己的系统监控工具。我在从设备接收的连续原始数据流上寻找 运行 过滤器(如高斯过滤器或类似过滤器)(在这种情况下是我的 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" 个数据点才能获得可靠的过滤值)。考虑到您的数据每秒测量五次,如果有必要,这可能是一个合理的折衷方案。