如何使用重复N次的最后一个非nan值在numpy数组中填充nan值



我想使用重复N次的最后一个非nan值来填充numpy数组中的nan值。如果nan值的数目>N、 然后用零填充其余的nan值。我如何在没有迭代的情况下以纯numpy进行操作?

import numpy as np
n = 2
arr = np.array([np.nan, 0, 0, np.nan, 5, 4, 4, np.nan, np.nan, np.nan, 1, 5, 3, np.nan, 2, np.nan, np.nan])
def ffill(arr: np.array, n: int):
pass
return arr
result = np.array([0.0, 0.0, 0.0, 0.0, 5.0, 4.0, 4.0, 4.0, 4.0, 0.0, 1.0, 5.0, 3.0, 3.0, 2.0, 2.0, 2.0])

Ffill 4 n次(=2([…4,np.nan,np.nn,np.na…]->[…4,4,0,]

【解决方案】

感谢@Homer512的回答。当n很大时,我改进了它。

def ffill(arr: np.array, n: int):
if np.isnan(arr[0]):
arr[0] = 0
isnan = np.isnan(arr)
notnan = ~isnan
valid = arr[notnan]
indices = np.cumsum(notnan) - 1
arr = valid[indices]
overlimit = np.lib.stride_tricks.sliding_window_view(isnan[:-1][::-1], isnan.size-n)[:, ::-1].all(axis=0)
overlimit &= isnan[n:]
indices = np.flatnonzero(overlimit) + n
arr[indices] = 0
return arr

这里有一个有效的技巧:

  1. 修复起始值
if math.isnan(arr[0]):
arr[0] = 0
  1. 现在我们可以使用np.cumsum跟踪有效索引
isnan = np.isnan(arr)
notnan = ~isnan
valid = arr[notnan]
indices = np.cumsum(notnan) - 1
arr = valid[indices]
  1. 为了支持在N个步骤后用零替换NaN的要求,可以使用np.convolve(isnan, (1,) * (n + 1), mode='same') > n来查找索引。但是因为卷积是居中的,所以从卷积中找到正确的索引有点复杂。让我们改为手动操作。是的,这将使用迭代,但对于N只有一个固定的数字
overlimit = np.copy(isnan[n:])
for i in range(1, n + 1):
overlimit &= isnan[n-i:-i]
indices = np.flatnonzero(overlimit) + n
arr[indices] = 0

最新更新