我有两个值,并且知道它们在一个充满nan的数组中的索引。我想插入/推断所有的南
import numpy as np
y = np.array([np.nan, np.nan, 0.75, np.nan, np.nan, np.nan, np.nan, np.nan, 2.25])
在这个答案的帮助下,我写了以下内容:
nans, x = np.isnan(y), lambda z: z.nonzero()[0]
y[nans] = np.interp(x(nans), x(~nans), y[~nans])
我的输出看起来如下:
[0.75 0.75 0.75]1.25 1.5 1.75 2。2.25)
但是,我希望它是:
[0.25 0.5 0.75]1.25 1.5 1.75 2。2.25)
增量总是一个常数。当我阅读np.iterp
的文档时,我看到我可以指定输入参数left
和right
。如果不指定left
,则x
我如何指定left
和right
以获得所需的输出?
np.interp
似乎没有外推,但scipy.interpolate.interp1d
有。
给出的参数有点不同,您可以根据您的特殊情况将其设置为函数:
import numpy as np
from scipy.interpolate import interp1d
def interp_nans(y, x=None):
if x is None:
x = np.arange(len(y))
nans = np.isnan(y)
interpolator = interp1d(
x[~nans],
y[~nans],
kind="linear",
fill_value="extrapolate",
assume_sorted=True,
)
return interpolator(x)
检查是否有效:
y = np.array([np.nan, np.nan, 0.75, np.nan, np.nan, np.nan, np.nan, np.nan, 2.25])
expected = np.array([0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25])
result = interp_nans(y)
assert np.array_equal(result, expected)
您不能指定left
和right
来实现与interp
的外推,它们只是常量值。
如果您喜欢纯numpy解决方案,您可以根据插值数组的前/后两个值进行线性外推:
def extrap(x, xp, fp):
m = (fp[1] - fp[0]) / (xp[1] - xp[0])
n = fp[0] - m * xp[0]
result = m * x[x < xp[0]] + n
m = (fp[-1] - fp[-2]) / (xp[-1] - xp[-2])
n = fp[-1] - m * xp[-1]
return np.concatenate([result, m * x[x > xp[-1]] + n])
(您可能希望添加验证len(xp) > 1
len(xp) == len(yp)
)
的例子:
y = np.array([np.nan, np.nan, 0.75, np.nan, np.nan, np.nan, np.nan, np.nan, 2.25, np.nan])
nans, x = np.isnan(y), lambda z: z.nonzero()[0]
y[nans] = np.interp(x(nans), x(~nans), y[~nans], np.nan, np.nan)
nans, x = np.isnan(y), lambda z: z.nonzero()[0]
y[nans] = extrap(x(nans), x(~nans), y[~nans])
结果array([0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. , 2.25])