沿轴插入numpy.ndarray的最佳方法

时间:2015-03-09 03:19:07

标签: python arrays optimization numpy interpolation

我有温度的四维数据,numpy.ndarray。 数组的形状为(ntime, nheight_in, nlat, nlon)

我为每个尺寸都有相应的1D数组,告诉我某个值对应的时间,高度,纬度和经度,对于这个例子,我需要height_in给出以米为单位的高度。

现在我需要将它带到不同的高度尺寸height_out,并且长度不同。

以下似乎做了我想要的事情:

ntime, nheight_in, nlat, nlon = t_in.shape

nheight_out = len(height_out)
t_out = np.empty((ntime, nheight_out, nlat, nlon))

for time in range(ntime):
    for lat in range(nlat):
        for lon in range(nlon):
            t_out[time, :, lat, lon] = np.interp(
                height_out, height_in, t[time, :, lat, lon]
            )

但是有3个嵌套循环,以及python和numpy之间的大量切换,我认为这不是最好的方法。

有关如何改善这一点的任何建议?感谢

3 个答案:

答案 0 :(得分:5)

scipy的{​​{3}}可以提供帮助:

import numpy as np
from scipy.interpolate import interp1d

ntime, nheight_in, nlat, nlon = (10, 20, 30, 40)

heights = np.linspace(0, 1, nheight_in)

t_in = np.random.normal(size=(ntime, nheight_in, nlat, nlon))
f_out = interp1d(heights, t_in, axis=1)

nheight_out = 50
new_heights = np.linspace(0, 1, nheight_out)
t_out = f_out(new_heights)

答案 1 :(得分:1)

我正在寻找一个类似的功能,它使用不规则间隔的坐标,最后编写了我自己的功能。据我所知,插值处理得很好,内存和速度方面的性能也非常好。我想我会在这里分享,以防其他人遇到这个问题寻找类似的功能:

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d as scipy1d

# toy coordinates and data
nx, ny, nz = 25, 30, 10
x = np.arange(nx)
y = np.arange(ny)
z = np.tile(np.arange(nz), (nx,ny,1)) + np.random.randn(nx, ny, nz)*.1
testdata = np.random.randn(nx,ny,nz) # x,y,z

# Desired z-coordinates (must be between bounds of z)
znew = np.tile(np.linspace(2,nz-2,50), (nx,ny,1)) + np.random.randn(nx, ny, 50)*0.01

# Inverse the coordinates for testing
z = z[..., ::-1]
znew = znew[..., ::-1]

# Now use own routine
ynew = interp_along_axis(testdata, z, znew, axis=2, inverse=True)

# Check some random profiles
for i in range(5):
    randx = np.random.randint(nx)
    randy = np.random.randint(ny)

    checkfunc = scipy1d(z[randx, randy], testdata[randx,randy], kind='cubic')
    checkdata = checkfunc(znew)

    fig, ax = plt.subplots()
    ax.plot(testdata[randx, randy], z[randx, randy], 'x', label='original data')
    ax.plot(checkdata[randx, randy], znew[randx, randy], label='scipy')
    ax.plot(ynew[randx, randy], znew[randx, randy], '--', label='Peter')
    ax.legend()
    plt.show()

这是测试它的一个小例子:

{{1}}

Example output of test function

答案 2 :(得分:0)

遵循numpy.interp的条件,可以将左/右边界分配给范围外的点,并在within_bounds = ...之后添加此行

out_lbound = (xi <= _x[0,...])
out_rbound = (_x[-1,...] <= xi)

newy[i, out_lbound] = _y[0, out_lbound]
newy[i, out_rbound] = _y[-1, out_rbound]
newy[i, ...] = ...之后的

如果我对@ Peter9192所使用的策略了如指掌,我认为这些变化是在同一行。我检查了一下,但也许有些奇怪的情况无法正常工作。