2017-11-25 196 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),那么将取决于窗口大小进一步减少数据。

如果你正在寻找一些平滑的函数来描述你的数据,那么你想要的是一个插值,而不是一个移动的平均值。否则,你必须从你的数据范围中补充一些点 - 一个更高风险的插值。