如何在左边找到最接近的值

问题描述

我有一个函数,我检测到了这个函数的峰值。我取了每个峰高度的一半,现在我想找到交点,仅在左侧,函数与经过峰高一半的线之间的交点。

请注意,在下图中,这条线并未完全经过峰的一半。实际上,每个峰都有一个特定的中间高度值,我需要找到左侧与该值的交点。

我的函数值是:

data= [2.50075550e+01  2.68589513e+01  2.88928569e+01  3.05468408e+01
 3.17558878e+01  3.28585597e+01  3.41860820e+01  3.56781188e+01
 3.68868815e+01  3.72671655e+01  3.65050587e+01  3.47342596e+01
 3.24647483e+01  3.02772213e+01  2.84592589e+01  2.68653782e+01
 2.51627240e+01  2.33132310e+01  2.18235229e+01 ...]

我使用 SciPy 的 find_peaks 得到了一半的高度

heights.append(signal.find_peaks(data,height=height)[1]['peak_heights'])

#Then calculating the half of each peak
          

解决方法

以下代码使用 How to find the exact intersection of a curve with y==0? 中的函数 find_roots。此函数搜索与给定半值对应的精确内插 x 值。该段仅限于前一个峰值和当前峰值之间的间隔,并从结果列表中获取最后一个根(如果有)。

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

def find_roots(x,y):
    s = np.abs(np.diff(np.sign(y))).astype(bool)
    return x[:-1][s] + np.diff(x)[s] / (np.abs(y[1:][s] / y[:-1][s]) + 1)

np.random.seed(11235)
x = np.linspace(0,20,500)
data = np.convolve(1.1 ** np.random.randn(x.size).cumsum(),np.ones(40),'same')
data -= data.min()
plt.plot(x,data,c='dodgerblue')
peaks,_ = signal.find_peaks(data,height=40,distance=50)

plt.scatter(x[peaks],data[peaks],color='turquoise')
for p,prev in zip(peaks,np.append(0,peaks)):
    half = data[p] / 2
    roots = find_roots(x[prev:p],data[prev:p] - half)
    if len(roots) > 0:
        plt.scatter(roots[-1],half,color='crimson')
plt.ylim(ymin=0)
plt.show()

example plot

,

我将简单地解释一下通用算法。基本逻辑是,简单地遍历一遍time[s]值,根据迭代的time[s]值找到高度值。您需要的唯一数据是该值,无论该值是否等于或大于您想要的相交线值,您都将使用该值。如果信号的高度等于或大于给定的 height 值,则表示存在交点,如果没有,则信号高度肯定小于您想要与信号相交的线值.