Python 使用for循环中的find_peaks从数据文件中查找峰值高度以计算平均值
这个问题是关于使用scipy.signal中的find_peaks有效地从数据文件中提取平均峰高。我是Python(3.7)的初学者,所以我不确定在速度和代码质量方面是否以最佳方式编写了代码 我有一套测量文件,每个文件包含一百万个数据点(30MB)。该数据的图形是一个具有固定间隔峰值和噪声的信号。此外,信号的基线和振幅随信号的不同部分而变化。我附上了一个例子的图片。信号可能不那么干净 我的目标是计算每个文件峰值的平均高度。为了做到这一点,首先我使用find_peaks来定位所有峰值。然后,我在每个峰值位置上循环,并在峰值周围的小间隔内检测峰值,以确保获得峰值的局部高度 然后我把所有这些高度放在numpy数组中,然后计算它们的平均值和标准偏差 这是我的代码的一个赤裸裸的版本,有点长,但我认为这也可能是因为我做错了什么Python 使用for循环中的find_peaks从数据文件中查找峰值高度以计算平均值,python,numpy,Python,Numpy,这个问题是关于使用scipy.signal中的find_peaks有效地从数据文件中提取平均峰高。我是Python(3.7)的初学者,所以我不确定在速度和代码质量方面是否以最佳方式编写了代码 我有一套测量文件,每个文件包含一百万个数据点(30MB)。该数据的图形是一个具有固定间隔峰值和噪声的信号。此外,信号的基线和振幅随信号的不同部分而变化。我附上了一个例子的图片。信号可能不那么干净 我的目标是计算每个文件峰值的平均高度。为了做到这一点,首先我使用find_peaks来定位所有峰值。然后,我在
将numpy导入为np
从scipy.signal导入查找\u峰值
#为值分配空列表
平均高度=[]
标准高度=[]
平均_基线=[]
标准单位基线=[]
温度=[]
#循环几个文件,读入它们并处理数据
对于文件列表中的文件:
附加(文件)
#从30 MB的文件加载数据
t_dat,x_dat=np.loadtxt(文件,分隔符='\t',unpack=True)
#查找此文件中的所有峰值
峰值,峰值属性=查找峰值(x_dat,突出度=峰值阈值,宽度=0)
#计算窗口大小,确保其均匀
如果为圆形(len(t_dat)/len(peaks))%2==0:
每个窗口的点数=整数(长(t数据)/长(峰值))
其他:
每窗口点数=int(len(t_dat)/len(peaks)+1)
t_切片=t_数据[-1]/len(t_数据)
#为存储高度分配np数组
基线列表=np.0(长度(峰值)-2)
高度列表=np.0(长度(峰值)-2)
#循环所有发现的峰值,并在峰值周围的窗口中重新检测峰值,以便
#检测其局部高度而不触发到远处的基线
对于范围(0,len(峰值)-2)内的i:
#在峰值周围创建一个窗口
sub_t=t_dat[峰值[i+1]-每个窗口的点//2:峰值[i+1]+每个窗口的点//2]
sub_x=x_dat[peaks[i+1]-每个_窗口的点//2:peaks[i+1]+每个_窗口的点//2]
#检测峰值(2个版本,特定于我拥有的应用程序)
突出度阈值奇数=最大值(sub_x)-np.平均值(sub_x)
sub_peaks_baseline,sub_peak_baseline_properties=查找_peaks(sub_x,突出度=突出度\u阈值\u单数,距离=每个窗口的点\u-1,宽度=0)
子峰高度,子峰高度属性=查找子峰(np.append(最小(子峰x)-1,子峰x),突出度=突出度阈值单数,距离=每个窗口的点数-1,宽度=0)
#将高度添加到存储高度的np数组中
基线列表[i]=次峰值基线属性[“突出物”]
高度列表[i]=次峰值高度属性[“突出物”]
#用值填充列表,用高度获取np数组的标准差和平均值
平均高度。追加(np.平均(高度列表))
标准高度附加(np.std(高度列表))
平均值基线。追加(np.平均值(基线列表))
标准基线追加(np.std(基线列表))
我希望它运行得相当快,但是执行起来需要几十秒。这对我来说似乎很慢,所以我开始认为我可能做这个分析效率低下。我的代码中是否有某些方面没有以正确的方式完成?还是我低估了执行此计算所需的时间
提前感谢所有想看一看的人。同时,我通过使用Python profiler发现的各种低效问题,提高了速度。我将在此处列出按速度重要性排序的优化:
- 对I/O使用pandas
而不是pd.read\u csv()
切断大约90%的运行时间。如前所述,这节省了大量时间。这意味着改变这一点:np.loadtxt()
为此:t_-dat,x_-dat=np.loadtxt(文件,分隔符='\t',unpack=True)
data=pd.read\u csv(文件,分隔符=“\t”,名称=[“t\u dat”,“x\u dat”]) t_dat=data.values[:,0] x_dat=data.values[:,1]
- 删除冗余的len()调用。我注意到len()被多次调用,然后注意到这是不必要的。更改此选项:
为此:如果为圆形(len(t_dat)/len(peaks))%2==0: 每个窗口的点数=整数(长(t数据)/长(峰值)) 其他: 每窗口点数=int(len(t_dat)/len(peaks)+1)
事实证明,这也是一项重大改进points\u per\u window=圆形(len(t\u dat)/len(peaks)) 如果每个窗口有%2个点!=0: 每窗口点数+=1
- 最后,内置Python函数min()、max()和sum()使用了不相称的计算时间(约20%)。由于我已经在使用numpy数组,因此在这些函数中切换到numpy等价物,这一部分得到了84%的改进。这意味着例如将
更改为max(sub_x)
sub_x.max()