我正在制作自己的系统监控工具。我希望在我从设备接收的连续原始数据流上运行过滤器(如高斯过滤器或类似过滤器)(在这种情况下为我的cpu%)。
数据值的集合长度为n
个元素。每次运行这段代码时,它会附加新的cpu值并删除最旧的,保留集合的长度为n
,基本上为deque([float('nan')] * n, maxlen=n)
,其中n
是图的长度i&# 39; m密谋。
然后它通过高斯滤波器过滤整个集合,创建平滑的数据点,然后绘制它们,创建一个类似于计算机上的大多数系统监视器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:寻找一种优化的方法来平滑原始流数据,而不是每次传递都过滤整个数据集。
答案 0 :(得分:1)
我从未使用过一个,但你需要的是听起来Savitzky–Golay filter的含义。它是一个本地平滑过滤器,可用于使数据更具可微分性(并区分它,而我们也可以区分它)。
好消息是版本0.14 scipy supports this filter。文档的相关部分:
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.
[...]
我首先确定一对小多项式阶数和窗口大小。您只需要平滑大约n
长度的deque
,而不是使用完整的window_length
数据点。当每个新数据点出现时,您必须将其附加到较小的deque
,应用Savitzky-Golay过滤器,获取新的过滤点,然后将其附加到图表中。
但请注意,在我看来,当不在数据集的边缘时,该方法大多定义得很好。这可能意味着,为了精确起见,您可能需要引入一些测量值'延迟,所以你总是可以使用给定窗口内的点(我的意思是,对于给定时间点你可能需要"未来"数据点以获得可靠的过滤值)。考虑到您的数据每秒测量五次,如果有必要,这可能是一个合理的妥协。