Python - 找到正态曲线的最小值、最大值和拐点
Python - Find min, max, and inflection points of normal curve
我试图找到植被中最小值、季节开始、生长旺季、最大生长、衰老、季节结束、最小值(即拐点)的位置(即 x 值)曲线。我在这里使用正态曲线作为示例。我确实遇到了一些代码来查找斜率和一阶/二阶导数的变化,但无法针对我的案例实现它们。如果有任何相关示例,请指导我,感谢您的帮助。谢谢!
## Version 2 code
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
x_min = 0.0
x_max = 16.0
mean = 8
std = 2
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, mean, std)
# Slice the group in 3
def group_in_threes(slicable):
for i in range(len(slicable)-2):
yield slicable[i:i+3]
# Locate the change in slope
def turns(L):
for index, three in enumerate(group_in_threes(L)):
if (three[0] > three[1] < three[2]) or (three[0] < three[1] > three[2]):
yield index + 1
# 1st inflection point estimation
dy = np.diff(y, n=1) # first derivative
idx_max_dy = np.argmax(dy)
ix = list(turns(dy))
print(ix)
# All inflection point estimation
dy2 = np.diff(dy, n=2) # Second derivative?
idx_max_dy2 = np.argmax(dy2)
ix2 = list(turns(dy2))
print(ix2)
# Graph
plt.plot(x, y)
#plt.plot(x[ix], y[ix], 'or', label='estimated inflection point')
plt.plot(x[ix2], y[ix2], 'or', label='estimated inflection point - 2')
plt.xlabel('x'); plt.ylabel('y'); plt.legend(loc='best');
这里有一个非常简单但不稳健的方法来找到无噪声曲线的拐点:
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
x_min = 0.0
x_max = 16.0
mean = 8
std = 2
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, mean, std)
# 1st inflection point estimation
dy = np.diff(y) # first derivative
idx_max_dy = np.argmax(dy)
# Graph
plt.plot(x, y)
plt.plot(x[idx_max_dy], y[idx_max_dy], 'or', label='estimated inflection point')
plt.xlabel('x'); plt.ylabel('y'); plt.legend();
拐点的实际位置是高斯曲线x1 = mean - std
。
为了使用真实数据,它们必须在寻找最大值之前进行平滑处理,例如应用一个简单的移动平均线,一个 gaussian filter or a Savitzky-Golay filter 可以直接输出二阶导数...选择正确的过滤器取决于数据
我试图找到植被中最小值、季节开始、生长旺季、最大生长、衰老、季节结束、最小值(即拐点)的位置(即 x 值)曲线。我在这里使用正态曲线作为示例。我确实遇到了一些代码来查找斜率和一阶/二阶导数的变化,但无法针对我的案例实现它们。如果有任何相关示例,请指导我,感谢您的帮助。谢谢!
## Version 2 code
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
x_min = 0.0
x_max = 16.0
mean = 8
std = 2
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, mean, std)
# Slice the group in 3
def group_in_threes(slicable):
for i in range(len(slicable)-2):
yield slicable[i:i+3]
# Locate the change in slope
def turns(L):
for index, three in enumerate(group_in_threes(L)):
if (three[0] > three[1] < three[2]) or (three[0] < three[1] > three[2]):
yield index + 1
# 1st inflection point estimation
dy = np.diff(y, n=1) # first derivative
idx_max_dy = np.argmax(dy)
ix = list(turns(dy))
print(ix)
# All inflection point estimation
dy2 = np.diff(dy, n=2) # Second derivative?
idx_max_dy2 = np.argmax(dy2)
ix2 = list(turns(dy2))
print(ix2)
# Graph
plt.plot(x, y)
#plt.plot(x[ix], y[ix], 'or', label='estimated inflection point')
plt.plot(x[ix2], y[ix2], 'or', label='estimated inflection point - 2')
plt.xlabel('x'); plt.ylabel('y'); plt.legend(loc='best');
这里有一个非常简单但不稳健的方法来找到无噪声曲线的拐点:
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
x_min = 0.0
x_max = 16.0
mean = 8
std = 2
x = np.linspace(x_min, x_max, 100)
y = norm.pdf(x, mean, std)
# 1st inflection point estimation
dy = np.diff(y) # first derivative
idx_max_dy = np.argmax(dy)
# Graph
plt.plot(x, y)
plt.plot(x[idx_max_dy], y[idx_max_dy], 'or', label='estimated inflection point')
plt.xlabel('x'); plt.ylabel('y'); plt.legend();
拐点的实际位置是高斯曲线x1 = mean - std
。
为了使用真实数据,它们必须在寻找最大值之前进行平滑处理,例如应用一个简单的移动平均线,一个 gaussian filter or a Savitzky-Golay filter 可以直接输出二阶导数...选择正确的过滤器取决于数据