对Numpy数组进行条件检查的有效方法



我正在尝试对numpy数组执行一些条件检查,我的代码现在不是很python。谁能建议更有效的方法来编写下面的代码?

  1. h是一个2D numpy数组的浮点数与尺寸窄*ncols
  2. bound是一个2D numpy数组,包含尺寸为nrows*ncols的整数
  3. L1TopOld是一个2D numpy数组的浮点数与尺寸窄*ncols
eps = 1.0e-04
#Fill in gaps in the surfaces#####################################
for i in range(nrows):
  for j in range(ncols):
      if (ibound[i,j] == 1 and fabs(h[i,j]-nodata) <= eps):
          h[i,j] = L1TopOld[i,j]

您可以使用np.where。首先,让我们制作一些玩具数据(顺便说一句,如果你自己做这部分会有所帮助):

>>> h = np.random.random((3,4))
>>> nodata = 10
>>> h.flat[[2,3,4,7,8,9]] = 10
>>> ibound = np.random.randint(0,2,(3,4))
>>> L1TopOld = np.ones((3,4))*5
>>> h
array([[  0.1382408 ,   0.7718657 ,  10.        ,  10.        ],
       [ 10.        ,   0.5595833 ,   0.83703255,  10.        ],
       [ 10.        ,  10.        ,   0.79473842,   0.91882331]])
>>> ibound
array([[0, 1, 1, 0],
       [0, 1, 1, 0],
       [0, 1, 0, 1]])
>>> L1TopOld
array([[ 5.,  5.,  5.,  5.],
       [ 5.,  5.,  5.,  5.],
       [ 5.,  5.,  5.,  5.]])
>>> eps = 0.01

现在我们可以决定我们想要修补的:

>>> ibound & (abs(h-nodata) <= eps)
array([[0, 0, 1, 0],
       [0, 0, 0, 0],
       [0, 1, 0, 0]])

,并使用它来告诉np.where我们想要切换到哪里:

>>> np.where(ibound & (abs(h - nodata) <= eps), L1TopOld, h)
array([[  0.1382408 ,   0.7718657 ,   5.        ,  10.        ],
       [ 10.        ,   0.5595833 ,   0.83703255,  10.        ],
       [ 10.        ,   5.        ,   0.79473842,   0.91882331]])

正如评论中指出的,这里假设ibound是一个仅由0和1组成的掩码。如果您真的只想更改ibound == 1(而不是2,例如)的情况,这也很容易:

>>> np.where((ibound == 1) & (abs(h - nodata) <= eps), L1TopOld, h)
array([[  0.1382408 ,   0.7718657 ,   5.        ,  10.        ],
       [ 10.        ,   0.5595833 ,   0.83703255,  10.        ],
       [ 10.        ,   5.        ,   0.79473842,   0.91882331]])

(这里给出相同的答案,因为0和1是ibound中仅有的数字)

如果要修改原始数组:

import numpy as np
eps = .01
nodata = 10
h = np.array([[0.1382408, 0.7718657, 10. , 10. ],
              [ 10. , 0.5595833, 0.83703255, 10. ],
              [ 10. , 10. , 0.79473842, 0.91882331]])
h.flat[[2,3,4,7,8,9]] = 10
ibound = np.array([[0, 1, 1, 0],
                   [0, 1, 1, 0],
                   [0, 1, 0, 1]])
L1TopOld = np.array([[ 5., 5., 5., 5.],
                     [ 5., 5., 5., 5.],
                     [ 5., 5., 5., 5.]])

用条件创建一个逻辑掩码:

mask = (ibound == 1) & (abs(h - nodata) <= eps)

使用布尔索引修改数组

h[mask] = L1TopOld[mask]
print h
[[  0.1382408    0.7718657    5.          10.        ]
 [ 10.           0.5595833    0.83703255  10.        ]
 [ 10.           5.           0.79473842   0.91882331]]

您只需要进行矢量方式:

cond = (ibound == 1) & (np.fabs(h - nodata) <= eps)
h[cond] = L1TopOld[cond]

让我们看一个例子(我正在使用前面评论中提出的那个):

>>> import numpy as np
>>> h = np.random.random((3, 4))
>>> nodata = 10
>>> h.flat[[2, 3, 4, 7, 8, 9]] = nodata
>>> ibound = np.random.randint(0, 2, (3, 4))
>>> L1TopOld = np.ones((3, 4)) * 5
>>> eps = 0.01
>>> ibound
array([[0, 0, 1, 0],
       [0, 0, 1, 1],
       [1, 1, 1, 1]])
>>> L1TopOld
array([[ 5.,  5.,  5.,  5.],
       [ 5.,  5.,  5.,  5.],
       [ 5.,  5.,  5.,  5.]])
>>> h
array([[  0.89332453,   0.71094897,  10.        ,  10.        ],
       [ 10.        ,   0.47419211,   0.50206745,  10.        ],
       [ 10.        ,  10.        ,   0.71388832,   0.84379527]])
>>> cond = (ibound == 1) & (np.fabs(h - nodata) <= eps)
>>> cond
array([[False, False,  True, False],
       [False, False, False,  True],
       [ True,  True, False, False]], dtype=bool)
>>> h[cond] = L1TopOld[cond]
>>> h
array([[  0.89332453,   0.71094897,   5.        ,  10.        ],
       [ 10.        ,   0.47419211,   0.50206745,   5.        ],
       [  5.        ,   5.        ,   0.71388832,   0.84379527]])

最新更新