在 pandas 中跨稀疏网格进行插值

Interpolate across sparse grid in pandas

我有一个数字网格(期权波动率,见下图),其中网格末端的条目很少(即非常稀疏)。我想通过使用整个网格的数据在这个网格中 interpolate\fill ,即二维插值方法。我看过一些例子(例如 here),但我不熟悉 scipy 和 numpy API,而且他们似乎在做一堆与实际插值。

明确地说,我目前将此数据存储在 pandas 数据框中,索引为 OPT_EXPIRE_DTOPT_STRIKE_PX,并希望在最后以另一个 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, 2, float('NaN')],[float('NaN'), 3, 4], [5, 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])