2013-04-14 50 views
4

我正在尋找一種快速高效的方法來計算一組數據的健壯,移動的尺度估計。我正在處理典型的3-400k元素的1d陣列。直到最近,我一直在使用模擬數據(沒有災難性的異常值),而優秀的Bottleneck包中的move_std函數爲我提供了很好的幫助。但是,由於我已經過渡到嘈雜的數據,標準不再有足夠的表現以至於有用。蟒蛇陣列的高效移動,健壯的尺度估計

在我用過去的很簡單biweight中等方差代碼元素的元素來處理性能欠佳分佈的問題:

def bwmv(data_array): 
    cent = np.median(data_array) 
    MAD = np.median(np.abs(data_array-cent)) 
    u = (data_array-cent)/9./MAD 
    uu = u*u 
    I = np.asarray((uu <= 1.), dtype=int) 
    return np.sqrt(len(data_array) * np.sum((data_array-cent)**2 * (1.-uu)**4 * I)\ 
      /(np.sum((1.-uu) * (1.-5*uu) * I)**2)) 

但是我現在有工作陣列足夠大,這是非常緩慢的。有沒有人知道提供這樣一個估算器的軟件包,或者有什麼建議如何以快速有效的方式來實現?

回答

3

我在類似的情況下使用了一個簡單的低通濾波器。

從概念上講,您可以通過fac = 0.99; filtered[k] = fac*filtered[k-1] + (1-fac)*data[k]獲得對平均值的移動估計值,這對於實現(在C中)非常有效。稍微更看中IIR濾波器比這一個,巴特沃斯低通,易於安裝在SciPy的:

b, a = scipy.signal.butter(2, 0.1) 
filtered = scipy.signal.lfilter(b, a, data) 

爲了得到一個估計的「規模」,你可以減去這個「意思是估計」從數據。這實際上將低通變成高通濾波器。取abs()並通過另一個低通濾波器運行。

結果可能是這樣的:

script output

完整的腳本:

from pylab import * 
from scipy.signal import lfilter, butter 

data = randn(1000) 
data[300:] += 1.0 
data[600:] *= 3.0 
b, a = butter(2, 0.03) 
mean_estimate = lfilter(b, a, data) 
scale_estimate = lfilter(b, a, abs(data-mean_estimate)) 

plot(data, '.') 
plot(mean_estimate) 
plot(mean_estimate + scale_estimate, color='k') 
plot(mean_estimate - scale_estimate, color='k') 

show() 

顯然,黃油()參數需要調整您的問題。如果您將順序設置爲1而不是2,那麼您會得到我首先描述的簡單過濾器。

聲明:這是一位工程師對此問題的看法。這種方法可能在任何統計或數學方面都不是很合理。另外,我不確定它是否真的解決了您的問題(請更好地解釋它,如果不這樣做),但不要擔心,無論如何,我都有過這樣的樂趣;-)