2017-11-25 194 views
0

This question關於如何獲得移動平均線有很多有用的答案。 我已經嘗試了numpy卷積和numpy cumsum這兩種方法,並且都在示例數據集上工作得很好,但在我的真實數據上生成了較短的數組。移動平均產生不同長度的數組?

數據被隔開0.01。示例數據集的長度爲50,真實數據爲數萬。所以它必須是造成問題的窗口大小,我不太明白函數中發生了什麼。

這是我如何定義功能:

def smoothMAcum(depth,temp, scale): # Moving average by cumsum, scale = window size in m 
    dz = np.diff(depth) 
    N = int(scale/dz[0]) 
    cumsum = np.cumsum(np.insert(temp, 0, 0)) 
    smoothed=(cumsum[N:] - cumsum[:-N])/N 
    return smoothed 

def smoothMAconv(depth,temp, scale): # Moving average by numpy convolution 
    dz = np.diff(depth) 
    N = int(scale/dz[0]) 
    smoothed=np.convolve(temp, np.ones((N,))/N, mode='valid') 
    return smoothed 

然後我實現它:

scale = 5. 
smooth = smoothMAconv(dep,data, scale) 

print len(dep), len(smooth) 回報81071 80572

,如果我使用其他功能相同的情況。 如何獲得與數據相同長度的平滑數組?

爲什麼它在小數據集上工作?即使我嘗試使用不同的比例尺(並且在示例和數據中使用相同的尺寸),但示例中的結果與原始數據的長度相同,但不在實際應用中。 我認爲nan值的影響,但如果我在示例中有nan,它沒有什麼區別。

那麼問題出在哪裏,如果可能的話沒有完整的數據集來判斷?

+0

通過模擬數據(例如我的答案中的一個隨機數組),可以包括一個具有大尺寸數據集的可重現示例。 – FTP

回答

1

第二種方法很容易修改以保持長度,因爲numpy.convolve支持參數mode='same'

np.convolve(temp, np.ones((N,))/N, mode='same') 

這是由零填充數據成爲可能設定temp兩側, - 這將不可避免地在邊界處有一定的影響,除非你的數據恰好是邊界附近0。例如:

N = 10 
x = np.linspace(0, 2, 100) 
y = x**2 + np.random.uniform(size=x.shape) 
y_smooth = np.convolve(y, np.ones((N,))/N, mode='same') 
plt.plot(x, y, 'r.') 
plt.plot(x, y_smooth) 
plt.show() 

smoothing

補零的邊界效應是在右端,其中數據點是約4-5,但用0

被填充爲降低非常明顯這種不希望的效果,使用numpy.pad更智能的填充;對於卷積,恢復爲mode='valid'。焊盤寬度必須是這樣的,即總共添加N-1個元素,其中N是移動窗口的大小。

y_padded = np.pad(y, (N//2, N-1-N//2), mode='edge') 
y_smooth = np.convolve(y_padded, np.ones((N,))/N, mode='valid') 

padding

填充由陣列的邊緣值看起來要好得多。

0

移動平均線的整點是平滑一個數組,並放棄一些數據點。它將幾乎按照定義縮短你的數組。考慮

1,2,3,4,5 

和移動平均爲2的窗口(一個實現中,一些可能使窗口獨家) - 所以你必須(1,2),(2,3),(4, 5)導致:

1.5,2.5,3.5,4.5 

這只是移動平均數的一個(通緝和預期)屬性。顯然「最平滑」陣列的數據長度相同,是您的數據。否則就沒有任何意義,假設你仍然希望數組能夠最好地表示原始數據。如果該窗口是排他性的,即(1,2),(3,4)(5),那麼將取決於窗口大小進一步減少數據。

如果你正在尋找一些平滑的函數來描述你的數據,那麼你想要的是一個插值,而不是一個移動的平均值。否則,你必須從你的數據範圍中補充一些點 - 一個更高風險的插值。