Python的滑动平均可以用卷积函数np.convolve实现的,但是对于数据边缘,要不就选择mode='valid'让两端数据缺失,要不选择mode='same'让边界的数据有偏差(边界效应),为了合理估计边缘的滑动值,往外扩展了2个数(用原序列边缘的数据求平均),自己写了一个1-2-4-2-1五点平滑。
import csv
def smooth_5(data):
import numpy as np
data=np.array(data)
# 扩展边缘值
data_02 = (data[0]+data[1]+data[2])/3.0
data_01 = (data[0]+data[1]+data[2]+data[3])/4.0
data_1 = (data[-1]+data[-2]+data[-3]+data[-4])/4.0
data_2 = (data[-1]+data[-2]+data[-3])/3.0
data = [data_02,data_01]+data+[data_1,data_2]
# 利用卷积函数平滑
arr_data = np.convolve(np.array(data),w/w.sum(),'valid')
return arr_data
Id=[]
with open('Id_norm.csv',encoding='gb18030',errors="ignore") as d:
csv_file = csv.reader(d)
for row in csv_file :
Id.append(row)
Id_norm=Id[1]
Id_5=smooth_5(Id_norm)
实测能用
同理,还可以做1-2-1,1-3-4-3-1等等滤波器,只需要修改相应系数即可。
但是这么设置还是有点麻烦的,每次使用都要改函数里面的内容,所以后来索性换一个思路,使用while循环先把数据两端扩展半个滑动窗口长度,再利用np.convolve并且选择mode='valid',让平滑后的序列与原序列长度相同,这样就可以直接把平滑窗各位置的权重写成一个元组或者列表,作为参数传进函数里计算了。
def smooth_weight(data,weight=(1,2,4,2,1)):
import numpy as np
data=np.array(data)
data_raw=data.copy()
w=np.array(weight)
# 扩展边缘
t=w.shape[0]-1
while t!=(w.shape[0]-1)/2:
data_head=np.array([np.nanmean(data_raw[:t])])
data_tail=np.array([np.nanmean(data_raw[-t:])])
data = np.concatenate((data_head,data,data_tail))
t -= 1
# 利用卷积函数平滑
arr_data = np.convolve(np.array(data),w/w.sum(),'valid')
return arr_data
Id=[]
with open('Id_norm.csv',encoding='gb18030',errors="ignore") as d:
csv_file = csv.reader(d)
for row in csv_file :
Id.append(row)
Id_norm=Id[1]
Id_5=smooth_weight(Id_norm,weight=(1,2,4,2,1))
Id_7=smooth_weight(Id_norm,weight=(1,2,3,4,3,2,1))
欢迎交流
祝各位科研顺利~