如何插值不规则比例的曲线?
How to interpolate a curve with irregular scale?
我有以下要在图表上显示的粒度数据,其中 x 是粒度,y 是概率密度函数。 x遵循一个几何序列(每个值乘以2)
X:[0.0,0.0781300000000005,0.1562600000000000001,0.312520000000000000002,0.6250400000000000004,1.25008000000001,2.50016000000002,5.000000000002,5.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000个
y: [0.0, 1.0512499897262986, 0.8764973224043381, 0.6221799472771921, 0.3760124741123981, 0.19346808043817057, 0.08474951460350254, 0.0316071940839253, 0.010035880788326037, 0.0]
这是图表:
我一直在尝试像 Excel 那样平滑曲线。我试过使用 interp1d(所有方法)、样条曲线、Akima1DInterpolator。
所以在我上面的评论中我说 很容易 。然而,问题是数据最后非常平坦。三次和更高阶插值不喜欢平面数据。它们倾向于 振荡 。如@f5r5e5d 所述,诀窍是重新缩放数据,使平坦部分变得非常短。在这种情况下,双对数刻度似乎还可以。不幸的是,这不适用于 y = 0
值。因此,要么必须删除该值,要么为它选择一个合理的小值(但不能太小,因为在双对数尺度上该点会漂移)。
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
xList = [0.078130000000000005, 0.15626000000000001, 0.31252000000000002, 0.62504000000000004, 1.2500800000000001, 2.5001600000000002, 5.0003200000000003, 10.000640000000001, 20.001280000000001]
yList = [ 1.0512499897262986, 0.8764973224043381, 0.6221799472771921, 0.3760124741123981, 0.19346808043817057, 0.08474951460350254, 0.0316071940839253, 0.010035880788326037, 0.0]
yList[-1] = 1.e-5 ###manually put a value for the zero
xLogList = [ np.log( x ) for x in xList ]
yLogList = [ np.log( y ) for y in yList ]
f = interp1d(xLogList, yLogList, kind='cubic')
xInterLogList = np.linspace( np.log( xList[0] ), np.log( xList[-1] ), 100 )
yInterLogList = [ f( x ) for x in xInterLogList ]
fig1=plt.figure()
ax=fig1.add_subplot( 1, 1, 1 )
ax.plot(xList, yList)
ax.plot( [ np.exp( x ) for x in xInterLogList ], [ np.exp( y ) for y in yInterLogList ] )
plt.show()
蓝色为原始数据,橙色为平滑插值。
我有以下要在图表上显示的粒度数据,其中 x 是粒度,y 是概率密度函数。 x遵循一个几何序列(每个值乘以2)
X:[0.0,0.0781300000000005,0.1562600000000000001,0.312520000000000000002,0.6250400000000000004,1.25008000000001,2.50016000000002,5.000000000002,5.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000个
y: [0.0, 1.0512499897262986, 0.8764973224043381, 0.6221799472771921, 0.3760124741123981, 0.19346808043817057, 0.08474951460350254, 0.0316071940839253, 0.010035880788326037, 0.0]
这是图表:
我一直在尝试像 Excel 那样平滑曲线。我试过使用 interp1d(所有方法)、样条曲线、Akima1DInterpolator。
所以在我上面的评论中我说 很容易 。然而,问题是数据最后非常平坦。三次和更高阶插值不喜欢平面数据。它们倾向于 振荡 。如@f5r5e5d 所述,诀窍是重新缩放数据,使平坦部分变得非常短。在这种情况下,双对数刻度似乎还可以。不幸的是,这不适用于 y = 0
值。因此,要么必须删除该值,要么为它选择一个合理的小值(但不能太小,因为在双对数尺度上该点会漂移)。
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
xList = [0.078130000000000005, 0.15626000000000001, 0.31252000000000002, 0.62504000000000004, 1.2500800000000001, 2.5001600000000002, 5.0003200000000003, 10.000640000000001, 20.001280000000001]
yList = [ 1.0512499897262986, 0.8764973224043381, 0.6221799472771921, 0.3760124741123981, 0.19346808043817057, 0.08474951460350254, 0.0316071940839253, 0.010035880788326037, 0.0]
yList[-1] = 1.e-5 ###manually put a value for the zero
xLogList = [ np.log( x ) for x in xList ]
yLogList = [ np.log( y ) for y in yList ]
f = interp1d(xLogList, yLogList, kind='cubic')
xInterLogList = np.linspace( np.log( xList[0] ), np.log( xList[-1] ), 100 )
yInterLogList = [ f( x ) for x in xInterLogList ]
fig1=plt.figure()
ax=fig1.add_subplot( 1, 1, 1 )
ax.plot(xList, yList)
ax.plot( [ np.exp( x ) for x in xInterLogList ], [ np.exp( y ) for y in yInterLogList ] )
plt.show()