问题描述
我有一个数字网格(选项波动率,见下图),其中网格末端的条目很少(即非常稀疏)。我想通过使用整个网格的数据来插入\填充这个网格,即二维插值方法。我看过一些例子(例如 here),但我不熟悉 scipy 和 numpy API,而且似乎他们正在做一堆与实际插值无关的图形。
明确地说,我目前将此数据存储在一个带有索引 OPT_EXPIRE_DT
和 OPT_STRIKE_PX
的 Pandas 数据帧中,并且希望在最后得到另一个 Pandas 数据帧,但我可以转换根据需要转换为其他数据类型。
感谢您的帮助!
解决方法
这是一个例子。让我们先创建一些缺失值的 DataFrame:
N = 5
df = pd.DataFrame(np.empty((N,N)))
df.iloc[:] = np.nan
df.iloc[:2] = 1
df.iloc[-2:] = 2
df
输出:
0 1 2 3 4
0 1.0 1.0 1.0 1.0 1.0
1 NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN NaN
4 2.0 2.0 2.0 2.0 2.0
然后我们可以使用 griddata
进行插值:
# create meshgrid
x,y = np.mgrid[0:N,0:N]
# find indices of non-missing values
ix_notna = df.notna().values
# interpolate
z_interpolated = interpolate.griddata(
(x[ix_notna],y[ix_notna]),df.values[ix_notna],(x,y),method='linear')
# griddata returns numpy array,so we convert it back to DataFrame
df_interpolated = pd.DataFrame(z_interpolated)
df_interpolated
输出:
0 1 2 3 4
0 1.00 1.00 1.00 1.00 1.00
1 1.25 1.25 1.25 1.25 1.25
2 1.50 1.50 1.50 1.50 1.50
3 1.75 1.75 1.75 1.75 1.75
4 2.00 2.00 2.00 2.00 2.00
我们可以直观地检查它是否按预期工作:
fig,ax = plt.subplots(1,2)
ax[0].imshow(df.values)
ax[0].set_title('original')
ax[1].imshow(df_interpolated.values)
ax[1].set_title('interpolated')
输出:
,所以,我认为您想要做的是转换为一个 numpy 数组并返回,这应该相当简单。这是通过线性插值计算简单数组的 NaN 条目值的代码。输出数组变为 np.array([[1,2,3],[2,3,4],[5,5.5,6]]).
from scipy.interpolate import interp2d
import numpy as np
# simple 2d array to interpolate
d = np.array([[1,float('NaN')],[float('NaN'),float('NaN'),6]])
# finds indices where values aren't NaN
valsX,valxY = np.where(np.isnan(d)==False)
# creates interpolation function from values that aren't NaN
interp = interp2d(valsX,valsY,d[valsX,valsY])
# copies original array in case you want to use it
dprime = np.copy(d)
# indices that are NaN we need to change
nanX,nanY = np.where(np.isnan(d))
# runs through all points with interpolation function
for i in range(len(nanX)):
dprime[nanX[i],nanY[i]] = interp(nanX[i],nanY[i])