Python 如何求多峰下的面积值

Python 如何求多峰下的面积值,python,numpy,matplotlib,scipy,peakutils,Python,Numpy,Matplotlib,Scipy,Peakutils,我有一些来自生物分析仪的数据,它给了我时间(x轴)和吸光度值(y轴)。时间是每0.05秒,从32秒到138秒,所以你可以想象我有多少数据点。我已经使用plotly和matplotlib创建了一个图形,这样我就有了更多的库来找到解决方案,所以在任何一个库中都可以找到解决方案!我要做的是让我的脚本找到每个峰值下的区域并返回我的值 def create_plot(sheet_name): sample = book.sheet_by_name(sheet_name) data = [[

我有一些来自生物分析仪的数据,它给了我时间(x轴)和吸光度值(y轴)。时间是每0.05秒,从32秒到138秒,所以你可以想象我有多少数据点。我已经使用plotly和matplotlib创建了一个图形,这样我就有了更多的库来找到解决方案,所以在任何一个库中都可以找到解决方案!我要做的是让我的脚本找到每个峰值下的区域并返回我的值

def create_plot(sheet_name):
    sample = book.sheet_by_name(sheet_name)
    data = [[sample.cell_value(r, c) for r in range(sample.nrows)] for c in range(sample.ncols)]
    y = data[2][18:len(data[2]) - 2]
    x = np.arange(32, 138.05, 0.05)
    indices = peakutils.indexes(y, thres=0.35, min_dist=0.1)
    peaks = [y[i] for i in indices]
这个片段获取我的Y值、X值和峰值的索引。现在有没有办法得到每条曲线下的面积?假设有15个指数

下面是图表的样子:

自动回答 给定一组
x
y
值以及一组
峰值
(峰值的
x
-坐标),以下是如何自动找到每个峰值下的区域。我假设
x
y
峰值
都是Numpy数组:

import numpy as np

# find the minima between each peak
ixpeak = x.searchsorted(peaks)
ixmin = np.array([np.argmin(i) for i in np.split(y, ixpeak)])
ixmin[1:] += ixpeak
mins = x[ixmin]

# split up the x and y values based on those minima
xsplit = np.split(x, ixmin[1:-1])
ysplit = np.split(y, ixmin[1:-1])

# find the areas under each peak
areas = [np.trapz(ys, xs) for xs,ys in zip(xsplit, ysplit)]
输出:

已设置示例数据,以确保每个峰值下的面积(或多或少)为
1.0
,因此底部图中的结果是正确的。绿色X标记是两个峰值之间的最小值位置。曲线“属于”每个峰值的部分被确定为曲线中靠近每个峰值的最小值之间的部分

完整代码 下面是我用来生成示例数据的完整代码:

import scipy as sp
import scipy.stats

prec = 1e5
n = 10
N = 150
r = np.arange(0, N+1, N//n)

# generate some reasonable fake data
peaks = np.array([np.random.uniform(s, e) for s,e in zip(r[:-1], r[1:])])
x = np.linspace(0, N + n, num=int(prec))
y = np.max([sp.stats.norm.pdf(x, loc=p, scale=.4) for p in peaks], axis=0)
我用来绘制图的代码是:

import matplotlib.pyplot as plt

# plotting stuff
plt.figure(figsize=(5,7))
plt.subplots_adjust(hspace=.33)
plt.subplot(211)
plt.plot(x, y, label='trace 0')
plt.plot(peaks, y[ixpeak], '+', c='red', ms=10, label='peaks')
plt.plot(mins, y[ixmin], 'x', c='green', ms=10, label='mins')
plt.xlabel('dep')
plt.ylabel('indep')
plt.title('Example data')
plt.ylim(-.1, 1.6)
plt.legend()

plt.subplot(212)
plt.bar(np.arange(len(areas)), areas)
plt.xlabel('Peak number')
plt.ylabel('Area under peak')
plt.title('Area under the peaks of trace 0')
plt.show()

你能澄清一下你是在寻找蓝色曲线下的区域,还是在红色探测到的峰值下的更大区域吗?@aorr所以我试图找到蓝色曲线下的区域。但对于每个由红点标识的单独峰值。希望澄清!如果我们在x轴上确定了我们想要“开始”每个确定的峰值的位置(我想你同意峰值是一个非典型的开始位置),那么我们可以通过简单的rieman梯形和找到面积。您的问题是关于如何检测索引值以确定一个峰值的起点,还是如何计算相邻蓝色值之间的梯形面积?这非常有用!最大的问题不是手动查找每个峰值的起点,而是有没有一种方法可以通过计算来完成?每个峰值索引之间的min()值可能是一个很好的起点。我建议更新该问题,以准确反映您正试图解决的问题的哪一部分,以及您被困的具体位置。