[英]Creating an incremental smooth spline curve instead of non-uniform increments in python
我正在嘗試使用樣條曲線平滑我的數據 - 這基本上是 y 軸上的累積百分位數和它們在 x 軸上引用的參考點。 我的大部分內容都是正確的,但是,我面臨的挑戰是我的 y 軸以非線性方式增加 - 正如下面樣條線 plot 所示 - y 軸值不斷增加和減少,而不僅僅是增加。
我仍然想要一條平滑的曲線,但希望 y 軸隨 x 軸增加 - 即每個后續 y 軸點的值應該等於或略微增加前一個值,而不是增加和減少。
可重現的代碼:
import pandas as pd
import numpy as np
from scipy.interpolate import make_interp_spline
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure
percentile_block_df = pd.DataFrame({
'x' : [0.5,100.5,200.5,400.5,800.5,900.5,1000.5],
'percentile' : [0.0001,0.01,0.065,0.85,0.99,0.9973,0.9999]
})
figure(figsize=(8, 6), dpi=80)
y = percentile_block_df.percentile
x = percentile_block_df.x
X_Y_Spline = make_interp_spline(x, y)
# Returns evenly spaced numbers
# over a specified interval.
X_ = np.linspace(x.min(), x.max(), 1000)
Y_ = X_Y_Spline(X_)
figure(figsize=(18, 6), dpi=80)
plt.subplot(1, 2, 1) # row 1, col 2 index 1
plt.plot(x, y,"ro")
plt.plot(x, y)
plt.title("Original")
plt.xlabel('X')
plt.ylabel('Percentile ')
plt.subplot(1, 2, 2) # index 2
plt.plot(x, y,"ro")
plt.plot(X_, Y_,"green")
plt.title("Spline Plot")
plt.xlabel('X')
plt.ylabel('Percentile ')
plt.show()
您正在尋找的是“保持單調性的插值”。 快速搜索顯示scipy.interpolate.PchipInterpolator
就是這樣做的。 這是您的示例的結果,只需插入from scipy.interpolate import PchipInterpolator
而不是from scipy.interpolate import make_interp_spline
。
這是否合適當然取決於您對插值的具體要求。 我鼓勵您研究現有的其他選項。
類似問題:
最終對我有用的代碼:
此鏈接解釋了單調三次插值的必要性
#this code allows "smoothening" of the data
B_spline_coeff1 = PchipInterpolator(x1, np.log(y1))
X1_Final = np.linspace(x.min(), x.max(), 1000)
Y1_Final = np.exp(B_spline_coeff1(X1_Final))
#plot subplots
figure(figsize=(18, 6), dpi=80)
plt.subplot(1, 2, 1) # row 1, col 2 index 1
plt.plot(x, y,"ro")
plt.plot(x, y)
plt.title("Original")
plt.xlabel('X')
plt.ylabel('Percentile ')
plt.subplot(1, 2, 2) # index 2
plt.plot(x, y,"ro")
plt.plot(X1_Final, Y1_Final,"green")
plt.title("Spline Plot")
plt.xlabel('X')
plt.ylabel('Percentile ')
plt.show()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.