Skip to main content
 首页 » 编程设计

python之用其前后值之间的线性插值替换 numpy 数组中的零

2025年05月04日18Terrylee

假设我们有一个数组a = np.array([1,2,0,4,0,5,0,0,11]),我们如何得到:

array([ 1,  2,  3,  4,  4.5,  5,  7,  9, 11]) 

我试过的是:

from scipy.interpolate import interp1d 
 
a = np.array([1,2,0,4,0,5,0,0,11]) 
b = a[np.nonzero(a)] 
brange = np.arange(b.shape[0]) 
interp = interp1d(brange, b) 

这似乎完成了查找中间值的实际工作。例如:

print (interp(1), interp(1.5), interp(2), interp(2.5), interp(3)) 
#out: 2.0 3.0 4.0 4.5 5.0 

但我不知道如何从 interp 重新构造我的原始数组。我还尝试了 this question 的解决方案,但我对该解决方案也有完全相同的问题。

更新:

我使用 numpy 和 pandas 对这两种解决方案进行了快速基准测试,结果如下:

y = np.array([1,2,0,4,0,5,0,0,11]) 
 
def test1(y): 
 
    x = np.arange(len(y)) 
    idx = np.nonzero(y) 
    interp = interp1d(x[idx],y[idx]) 
 
    return interp(x) 
 
def test2(y): 
    s = pd.Series(y) 
    s.interpolate(inplace=True) 
    return s.values 
 
%timeit t1 = test1(y) 
%timeit t2 = test2(y) 
 
139 µs ± 1.62 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) 
158 µs ± 2.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) 

大约快 12%。没有我希望的那么好,但由于代码将运行数百万次,所以这可能是值得的。

请您参考如下方法:

您需要向 interp1d 提供一个 没有 零的 y 数组和一个跳过所述零的 x 数组。然后,对于插值,您必须为插值函数提供一个 x 数组,其中包含所有原始 x 值以及您希望插值出现的 x 值。在你的情况下,因为你有一个准备好的、等距的向量,你可以只使用 np.arange 来产生 x 值和 np.where 来过滤掉零.

这里是一个示例代码:

import numpy as np 
from scipy.interpolate import interp1d 
 
y = np.array([1,2,0,4,0,5,0,0,11]) 
xnew = np.arange(len(y)) 
 
zero_idx = np.where(y==0) 
xold = np.delete(xnew,zero_idx) 
yold = np.delete(y, zero_idx) 
 
print('before') 
print(xold) 
print(yold) 
 
f = interp1d(xold,yold) 
 
ynew = f(xnew) 
 
print() 
print('after') 
print(xnew) 
print(ynew) 

结果是这样的:

before 
[0 1 3 5 8] 
[ 1  2  4  5 11] 
 
after 
[0 1 2 3 4 5 6 7 8] 
[  1.    2.    3.    4.    4.5   5.    7.    9.   11. ] 

编辑:

其实你不需要np.delete,你可以只使用切片:

y = np.array([1,2,0,4,0,5,0,0,11]) 
x = np.arange(len(y)) 
idx = np.where(y!=0)        #or np.nonzero(y) -- thanks DanielF 
f = interp1d(x[idx],y[idx]) 
ynew = f(x)