在Python中过滤1D numpy数组
说明: 我有两个numpy数组:dataX和dataY,我试图对每个数组进行过滤以减少噪声。下图显示了实际的输入数据(蓝色点)和我想要的示例(红色点)。我不需要像示例中那样完美地过滤数据,但我确实希望它尽可能直接。我在代码中提供了示例数据。 我尝试过的: 首先,您可以看到数据不是“连续的”,所以我首先将它们划分为单独的“段”(本例中有4个),然后对每个“段”应用过滤器。有人建议我使用一种新的方法。完整的可运行代码如下所示:在Python中过滤1D numpy数组,python,scipy,filtering,Python,Scipy,Filtering,说明: 我有两个numpy数组:dataX和dataY,我试图对每个数组进行过滤以减少噪声。下图显示了实际的输入数据(蓝色点)和我想要的示例(红色点)。我不需要像示例中那样完美地过滤数据,但我确实希望它尽可能直接。我在代码中提供了示例数据。 我尝试过的: 首先,您可以看到数据不是“连续的”,所以我首先将它们划分为单独的“段”(本例中有4个),然后对每个“段”应用过滤器。有人建议我使用一种新的方法。完整的可运行代码如下所示: import scipy as sc import scipy.sig
import scipy as sc
import scipy.signal
import numpy as np
import matplotlib.pyplot as plt
# Sample Data
ydata = np.array([1,0,1,2,1,2,1,0,1,1,2,2,0,0,1,0,1,0,1,2,7,6,8,6,8,6,6,8,6,6,8,6,6,7,6,5,5,6,6, 10,11,12,13,12,11,10,10,11,10,12,11,10,10,10,10,12,12,10,10,17,16,15,17,16, 17,16,18,19,18,17,16,16,16,16,16,15,16])
xdata = np.array([1,2,3,1,5,4,7,8,6,10,11,12,13,10,12,13,17,16,19,18,21,19,23,21,25,20,26,27,28,26,26,26,29,30,30,29,30,32,33, 1,2,3,1,5,4,7,8,6,10,11,12,13,10,12,13,17,16,19,18,21,19,23,21,25,20,26,27,28,26,26,26,29,30,30,29,30,32])
# Used a diff array to find where there is a big change in Y.
# If there's a big change in Y, then there must be a change of 'segment'.
diffy = np.diff(ydata)
# Create empty numpy arrays to append values into
filteredX = np.array([])
filteredY = np.array([])
# Chose 3 to be the value indicating the change in Y
index = np.where(diffy >3)
# Loop through the array
start = 0
for i in range (0, (index[0].size +1) ):
# Check if last segment is reached
if i == index[0].size:
print xdata[start:]
partSize = xdata[start:].size
# Window length must be an odd integer
if partSize % 2 == 0:
partSize = partSize - 1
filteredDataX = sc.signal.savgol_filter(xdata[start:], partSize, 3)
filteredDataY = sc.signal.savgol_filter(ydata[start:], partSize, 3)
filteredX = np.append(filteredX, filteredDataX)
filteredY = np.append(filteredY, filteredDataY)
else:
print xdata[start:index[0][i]]
partSize = xdata[start:index[0][i]].size
if partSize % 2 == 0:
partSize = partSize - 1
filteredDataX = sc.signal.savgol_filter(xdata[start:index[0][i]], partSize, 3)
filteredDataY = sc.signal.savgol_filter(ydata[start:index[0][i]], partSize, 3)
start = index[0][i]
filteredX = np.append(filteredX, filteredDataX)
filteredY = np.append(filteredY, filteredDataY)
# Plots
plt.plot(xdata,ydata, 'bo', label = 'Input Data')
plt.plot(filteredX, filteredY, 'ro', label = 'Filtered Data')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Result')
plt.legend()
plt.show()
这是我的结果:
连接每个点后,结果如下所示。
我已经试过了,但看起来第三个订单的效果最好
我还尝试了以下几种过滤器:
但到目前为止,我尝试过的过滤器中没有一个接近我真正想要的。过滤此类数据的最佳方法是什么?期待您的帮助 一种接近理想的方法是聚类+线性回归 请注意,您必须提供集群的数量,在集群之前,我在扩展
y
时也做了一些欺骗
一种接近理想的方法是聚类+线性回归 请注意,您必须提供集群的数量,在集群之前,我在扩展
y
时也做了一些欺骗
你好,保罗。谢谢你花时间回答:)我有几个问题:你总是需要放大Y还是只针对这种情况?如果是这样,我如何知道它的规模?我目前正在阅读有关集群的文章,但它似乎有点复杂。您是否介意在代码中添加注释,简要解释“split_to_lines”函数中的每一行的作用?@user3451660集群就我所知——我不是专家——不是一门精确的科学。但我认为当星系团有点圆的时候效果最好。现在,在您的数据中,集群在
x
方向上被拉长,因此我拉伸y
作为一个快速修复。对不起,我不能说得更具体了。我会看看我能为评论做些什么,谢谢!那么从技术上讲,只过滤Ydata?如果我必须连接每一个点,(见附加图片),我的原始显示X增加,直到X大幅度减少,而你的略有不同。此外,使用您的方法,我还需要计算要拆分的行数(示例中有4行,但可能更多)?@user3451660 Yes和Yes。但是你可以简单地对每个簇内的点进行排序。谢谢你花时间回答:)我有几个问题:你总是需要放大Y还是只针对这种情况?如果是这样,我如何知道它的规模?我目前正在阅读有关集群的文章,但它似乎有点复杂。您是否介意在代码中添加注释,简要解释“split_to_lines”函数中的每一行的作用?@user3451660集群就我所知——我不是专家——不是一门精确的科学。但我认为当星系团有点圆的时候效果最好。现在,在您的数据中,集群在x
方向上被拉长,因此我拉伸y
作为一个快速修复。对不起,我不能说得更具体了。我会看看我能为评论做些什么,谢谢!那么从技术上讲,只过滤Ydata?如果我必须连接每一个点,(见附加图片),我的原始显示X增加,直到X大幅度减少,而你的略有不同。此外,使用您的方法,我还需要计算要拆分的行数(示例中有4行,但可能更多)?@user3451660 Yes和Yes。但是您可以简单地对每个集群中的点进行排序。
import numpy as np
from scipy import cluster, stats
ydata = np.array([1,0,1,2,1,2,1,0,1,1,2,2,0,0,1,0,1,0,1,2,7,6,8,6,8,6,6,8,6,6,8,6,6,7,6,5,5,6,6, 10,11,12,13,12,11,10,10,11,10,12,11,10,10,10,10,12,12,10,10,17,16,15,17,16, 17,16,18,19,18,17,16,16,16,16,16,15,16])
xdata = np.array([1,2,3,1,5,4,7,8,6,10,11,12,13,10,12,13,17,16,19,18,21,19,23,21,25,20,26,27,28,26,26,26,29,30,30,29,30,32,33, 1,2,3,1,5,4,7,8,6,10,11,12,13,10,12,13,17,16,19,18,21,19,23,21,25,20,26,27,28,26,26,26,29,30,30,29,30,32])
def split_to_lines(x, y, k):
yo = np.empty_like(y, dtype=float)
# get the cluster centers and the labels for each point
centers, map_ = cluster.vq.kmeans2(np.array((x, y * 2)).T.astype(float), k)
# for each cluster, use the labels to select the points belonging to
# the cluster and do a linear regression
for i in range(k):
slope, interc, *_ = stats.linregress(x[map_==i], y[map_==i])
# use the regression parameters to construct y values on the
# best fit line
yo[map_==i] = x[map_==i] * slope + interc
return yo
import pylab
pylab.plot(xdata, ydata, 'or')
pylab.plot(xdata, split_to_lines(xdata, ydata, 4), 'ob')
pylab.show()