1D numpy / scipy插值不是1D

时间:2013-10-16 17:26:58

标签: python arrays numpy interpolation

Numpy数组data有....数据。 Numpy数组z有距离。数据和z具有相同的形状,z的每个点是测量相应数据点的距离。更复杂的是,用户将提供具有3,4或5维的data / z数组。

我想将数据插值到1D numpy数组dists中的一组距离。由于数据结构,插值轴总是从两端开始,即如果数组有3个维,则插值轴为0;如果数组有4个维,插值轴是1,等等。因为,AFAICT,所有numpy / scipy插值例程都希望在1D数组中给出原始距离,插入数据和z在dists上似乎是一个有点复杂的任务。这就是我所拥有的:

def dist_interp(data, z, dists):
    # construct array to hold interpolation results
    num_dims = len(data.shape)
    interp_axis = num_dims-3
    interp_shape = list(data.shape)
    interp_shape[interp_axis] = dists.shape[0]
    interp_res = np.zeros(shape=interp_shape)
    # depending on usage, data could have between 3 and five dimensions.
    # add dims to generalize.  I hate doing it this way.  Must be
    # some other way.
    for n in range(num_dims, 5) :
        data = np.expand_dims(data, axis=0)
        z = np.expand_dims(z, axis=0)
        interp_res = np.expand_dims(interp_res, axis=0)
    for m in range(data.shape[0]):
        for l in range(data.shape[1]):
            for j in range(data.shape[3]):
                for i in range(data.shape[4]):
                    interp_res[m,l,:,j,i]=(
                                  np.interp(dists,z[m,l,:,j,i],
                                            data[m,l,:,j,i]))
    # now remove extra "wrapping" dimensions
    for n in range(0,5-num_dims):
        interp_res = interp_res[0]
    return(interp_res)

我认为这样可行,但添加和删除额外的“包装”虚拟尺寸是非常不优雅的,并且使代码完全不紧凑。有更好的想法吗?感谢。

1 个答案:

答案 0 :(得分:4)

作为这种情况的一般经验法则:

  1. 将您要做的东西移动到形状元组的末尾
  2. 将结果数组重新整形为2D
  3. 从此2D
  4. 创建新阵列
  5. 撤消新阵列的步骤2和1
  6. 对于您的情况,它可能看起来像:

    # Create some random test data
    axis = -2
    shape = np.random.randint(10, size=(5,))
    data = np.random.rand(*shape)
    data = np.sort(data, axis=axis)
    z = np.random.rand(*shape)
    dists = np.linspace(0,1, num=100)
    
    data = np.rollaxis(data, axis, data.ndim)
    new_shape = data.shape
    data = data.reshape(-1, data.shape[-1])
    z = np.rollaxis(z, axis, z.ndim)
    z = z.reshape(-1, z.shape[-1])
    
    out = np.empty(z.shape[:1]+dists.shape)
    for o, x, f in zip(out, data, z):
        o[:] = np.interp(dists, x, f)
    
    out = out.reshape(new_shape[:-1]+dists.shape)
    out = np.rollaxis(out, -1, axis)