在3D numpy数组列上迭代,然后将值更改为邻居,如果在一个数字下面



i具有一个3D numpy阵列,带有浮子,如果值小于值(vmin),则需要将每个元素的值替换为邻居(i-1)。实施的代码效率很低:

def replace_values(B,vmin,nt,nx,ny):
    # B is a numpy array 
    # nt, nx ny the dimensions
    for z in xrange(0,nt):
        print i
        for y in xrange(0,ny):
            values=B[z,:,y]
            if numpy.amin(values)==0:
                for x in xrange(1,nx):
                    if B[z,x,y]<vmin:
                        B[z,x,y]=B[z,x-1,y]
    return B    

有什么方法可以实现迭代器以提高速度?

我拥有数组大小的一个限制,几乎是RAM内存的大小,无法完成副本。

看起来您的内部循环在1D视图上工作,因此可以编码为:

In [386]: values=np.random.randint(0,10,20)
In [387]: values
Out[387]: array([1, 5, 9, 4, 6, 7, 1, 5, 6, 4, 4, 3, 9, 5, 8, 5, 0, 3, 1, 2])
In [388]: np.amin?
In [389]: for x in range(1,len(values)):
     ...:     if values[x]<5:
     ...:         values[x]=values[x-1]
     ...:         
In [390]: values
Out[390]: array([1, 5, 9, 9, 6, 7, 7, 5, 6, 6, 6, 6, 9, 5, 8, 5, 5, 5, 5, 5])

如果是这样,一个目标是加快它的速度,可能是使用UFUNC accumulate功能之一(想想cumsum的动作)。

下一个问题是,我们可以避免在其他两个维度上进行迭代。有了一些转置和重塑,我们可以将其浓缩到1D的迭代中,但这并不能节省时间。在2D数组上测试想法比3D更容易。

我要建议apply_along_axis来照顾迭代的详细信息,但它不用,甚至不使用out参数)。

======================

让我们尝试将此操作应用于2D数组的所有值。

In [398]: val2d=np.array((x1,x1+2, x1-2))
In [399]: val2d
Out[399]: 
array([[ 1,  5,  9,  4,  6,  7,  1,  5,  6,  4,  4,  3,  9,  5,  8,  5,  0,  3,  1,  2],
       [ 3,  7, 11,  6,  8,  9,  3,  7,  8,  6,  6,  5, 11,  7, 10,  7,  2,  5,  3,  4],
       [-1,  3,  7,  2,  4,  5, -1,  3,  4,  2,  2,  1,  7,  3,  6,  3, -2,  1, -1,  0]])
In [400]: for i in range(1,val2d.shape[1]):
     ...:     mask = val2d[:,i]<5
     ...:     val2d[mask,i]=val2d[mask,i-1]
     ...:     
In [401]: val2d
Out[401]: 
array([[ 1,  5,  9,  9,  6,  7,  7,  5,  6,  6,  6,  6,  9,  5,  8,  5,  5,  5,  5,  5],
       [ 3,  7, 11,  6,  8,  9,  9,  7,  8,  6,  6,  5, 11,  7, 10,  7,  7,  5,  5,  5],
       [-1, -1,  7,  7,  7,  5,  5,  5,  5,  5,  5,  5,  7,  7,  6,  6,  6,  6,  6,  6]])

然后,此3D版本应起作用(未测试):

for i in range(1, B.shape[1]):
    mask = B[:,i,:]<vmin
    I,J = np.where(mask)
    B[I,i,J] = B[I,i-1,J]

这是使用示例1D数据以简单方式描述的问题。

假设输入数据数组是:

In [398]: a
Out[398]: array([4, 8, 2, 6, 3])

假设掩码基于要进行的数据是基于哪个数据(填充要在错误的位置上完成):

In [407]: mask
Out[407]: array([ True,  True, False,  True, False], dtype=bool)

首先,我们创建了一个基于蒙版的索引数组

In [409]: mask*np.arange(mask.size)
Out[409]: array([0, 1, 0, 3, 0])

接下来,我们确实累积了,它向前填充了基于掩蔽的零件数组 -

In [410]: np.maximum.accumulate( mask*np.arange(mask.size) )
Out[410]: array([0, 1, 1, 3, 3])

因此,最后一步是简单地用这些累积索引阵列索引数据数组 -

In [411]: a[np.maximum.accumulate( mask*np.arange(mask.size) )]
Out[411]: array([4, 8, 8, 6, 6])

如果您将其与原始数据阵列进行了比较,我们将其转发在蒙版的False位置上。

最终实现

让我们将前面列出的基于np.maximum.accumulate的解决方案扩展到几乎没有索引方法的3D情况

nt, nx, ny = B.shape
d0,d2 = np.where(B.min(1)==0)    
dim2_idx = np.maximum.accumulate( (B[d0,:,d2]>=vmin)*np.arange(nx), axis=1)
B[d0[:,None],np.arange(nx),d2[:,None]] = B[d0[:,None],dim2_idx,d2[:,None]]

相关内容

最新更新