关于如何获得移动平均线,这个问题有很多有用的答案.我已经尝试了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
Run Code Online (Sandbox Code Playgroud)
然后我实现它:
scale = 5.
smooth = smoothMAconv(dep,data, scale)
Run Code Online (Sandbox Code Playgroud)
但是print len(dep), len(smooth)
回归81071 80572
如果我使用其他功能,也会发生同样的情况.如何获得与数据长度相同的平滑数组?
为什么它适用于小型数据集?即使我尝试不同的比例(并且对于示例和数据使用相同的比例),示例中的结果与原始数据具有相同的长度,但在实际应用程序中却没有.我考虑了nan值的影响,但如果我nan在示例中有一个,它没有什么区别.
那么问题在哪里,如果可能的话,没有完整的数据集?
小智 6
您的第二种方法很容易修改以保留长度,因为numpy.convolve支持参数mode='same'.
np.convolve(temp, np.ones((N,))/N, mode='same')
Run Code Online (Sandbox Code Playgroud)
这可以通过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()
Run Code Online (Sandbox Code Playgroud)
零填充的边界效应在右端非常明显,其中数据点大约为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')
Run Code Online (Sandbox Code Playgroud)
按阵列边缘值填充看起来要好得多.