在Python中对1D数据执行移动线性拟合

时间:2011-09-02 19:05:01

标签: python numpy scipy

我有一维数据数据,希望提取空间变化。我希望pythonize的标准方法是对数据执行移动线性回归并保存渐变...

def nssl_kdp(phidp, distance, fitlen):
    kdp=zeros(phidp.shape, dtype=float)
    myshape=kdp.shape
    for swn in range(myshape[0]):
        print "Sweep ", swn+1
        for rayn in range(myshape[1]):
            print "ray ", rayn+1
            small=[polyfit(distance[a:a+2*fitlen], phidp[swn, rayn, a:a+2*fitlen],1)[0] for a in xrange(myshape[2]-2*fitlen)]
            kdp[swn, rayn, :]=array((list(itertools.chain(*[fitlen*[small[0]], small, fitlen*[small[-1]]]))))
    return kdp

效果不错但很慢......我需要这样做17 * 360次......

我认为开销是在[for arange]行中的迭代器中...在numpy / scipy中是否存在移动拟合的实现?

3 个答案:

答案 0 :(得分:3)

线性回归的计算基于各种值的总和。因此,您可以编写一个更有效的例程,在窗口移动时修改总和(添加一个点并减去前一个点)。

这比每次窗口移动时重复该过程更有效,但是对于舍入错误是开放的。所以你需要偶尔重启。

通过预先计算所有x依赖关系,你可能比等间距更好,但我不明白你的例子,所以我不确定它是否相关。

所以我想我只是假设它是。

斜率为(NΣXY - (ΣX)(ΣY))/(NΣX2 - (ΣX)2)其中“2”为“平方” - http://easycalculation.com/statistics/learn-regression.php

对于均匀间隔的数据,分母是固定的(因为您可以将x轴移动到窗口的开头而不改变渐变)。分子中的(ΣX)也是固定的(出于同样的原因)。所以你只需要关注ΣXY和ΣY。后者是微不足道的 - 只需添加和减去一个值。前者减少ΣY(每个X加权减少1)并且每步增加(N-1)Y(假设x_0为0,x_N为N-1)。

我怀疑还不清楚。我所说的是斜率的公式不需要在每一步都完全重新计算。特别是因为在每一步中,您可以将X值重命名为0,1,... N-1而不改变斜率。因此,公式中的几乎所有内容都是相同的。所有这些变化都是两个术语,取决于Y,Y_0“退出”窗口,Y_N“移入”。

答案 1 :(得分:1)

答案 2 :(得分:1)

好的..我有一个似乎是一个解决方案..不是一个答案,但是一种做出移动,多点差异的方法......我测试了这个,结果看起来非常类似于一个移动回归...我使用了1D sobel滤波器(斜率从-1到1与数据卷积):

def KDP(phidp, dx, fitlen):
    kdp=np.zeros(phidp.shape, dtype=float)
    myshape=kdp.shape
    for swn in range(myshape[0]):
        #print "Sweep ", swn+1
        for rayn in range(myshape[1]):
            #print "ray ", rayn+1
            kdp[swn, rayn, :]=sobel(phidp[swn, rayn,:], window_len=fitlen)/dx
    return kdp

def sobel(x,window_len=11):
    """Sobel differential filter for calculating KDP
    output:
        differential signal (Unscaled for gate spacing
        example:
    """
    s=np.r_[x[window_len-1:0:-1],x,x[-1:-window_len:-1]]
    #print(len(s))
    w=2.0*np.arange(window_len)/(window_len-1.0) -1.0
    #print w
    w=w/(abs(w).sum())
    y=np.convolve(w,s,mode='valid')
    return -1.0*y[window_len/2:len(x)+window_len/2]/(window_len/3.0)

这样跑得快!