簡體   English   中英

在Python中過濾一維numpy數組

[英]Filtering 1D numpy arrays in Python

說明:

我有兩個numpy數組:dataX和dataY,並且我試圖過濾每個數組以減少噪音。 下圖顯示了實際的輸入數據(藍點)和我想要的示例(紅點)的示例。 我不需要經過過濾的數據像示例中那樣完美,但我希望它盡可能地直接。 我在代碼中提供了示例數據。 在此處輸入圖片說明

我嘗試過的

首先,您可以看到數據不是“連續的”,因此我首先將它們划分為單獨的“段”(在此示例中為4個),然后對每個“段”應用過濾器。 有人建議我使用Savitzky-Golay濾波器 完整的可運行代碼如下:

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也作了一些欺騙。 在此處輸入圖片說明

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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM