我有一个指数衰减,如x和y值的图形,在下图中标记了一个转折点。我的问题是,有无噪声,如何使用Python检测转折的区域或中间点?值在此link中给定的csv文件中。

更新:这是更清晰的图表,显示了转折点/更改点。

python - 如何使用Python检测图的转折点-LMLPHP

最佳答案

一种简单的解决方法是使用np.gradient和阈值。

import numpy as np
from matplotlib import pyplot as plt

# generate some toy data
n = 600
t = np.linspace(0, 600, n)
y = (300 * np.exp(-0.1 * t) + 1) + 20 * (np.random.random(n))

# get the gradient
dy = np.gradient(y)

# search gradient for first occurrence of thresh value:
thresh = 0.01
idx_thresh = np.argmax(dy > thresh)
# y[idx_thresh] would be the "turning point"

# visualization
plt.plot(t, y, 'b', label='y')
plt.plot(t, dy, 'g', label='dy')
plt.plot(t[idx_thresh:], y[idx_thresh:], 'r', label=f'y[dy > {thresh}]')
plt.legend()


python - 如何使用Python检测图的转折点-LMLPHP

但是,找到阈值的位置很大程度上取决于噪声!因此,您可能需要进行一些平滑处理,例如

from scipy.signal import savgol_filter

y_filtered = savgol_filter(y, 11, 3)
dy_f = np.gradient(y_filtered)
idx_thresh = np.argmax(dy_f > thresh)

plt.plot(t, y_filtered, 'k', label='y_filtered')
plt.plot(t, dy_f, 'g', label='dy_f')
plt.plot(t[idx_thresh:], y[idx_thresh:], 'r', label=f'y[dy > {thresh}]')
plt.legend()


python - 如何使用Python检测图的转折点-LMLPHP

请注意,渐变现在更加平滑。重要提示:取决于输入数据,哪个过滤器合适!

10-04 22:00