在 pandas 中跨稀疏网格进行插值
Interpolate across sparse grid in pandas
我有一个数字网格(期权波动率,见下图),其中网格末端的条目很少(即非常稀疏)。我想通过使用整个网格的数据在这个网格中 interpolate\fill ,即二维插值方法。我看过一些例子(例如 here),但我不熟悉 scipy 和 numpy API,而且他们似乎在做一堆与实际插值。
明确地说,我目前将此数据存储在 pandas 数据框中,索引为 OPT_EXPIRE_DT
和 OPT_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])
我有一个数字网格(期权波动率,见下图),其中网格末端的条目很少(即非常稀疏)。我想通过使用整个网格的数据在这个网格中 interpolate\fill ,即二维插值方法。我看过一些例子(例如 here),但我不熟悉 scipy 和 numpy API,而且他们似乎在做一堆与实际插值。
明确地说,我目前将此数据存储在 pandas 数据框中,索引为 OPT_EXPIRE_DT
和 OPT_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])