我只需要选择3d二进制数组的非零3d部分(或布尔数组的真实值)。目前,我可以使用一系列使用np.any的“ for”循环来做到这一点,但这确实可行,但似乎很尴尬且缓慢,因此目前正在研究一种更直接的方法来完成任务。
我对numpy相当陌生,因此我尝试过的方法包括a)使用 np.nonzero,它返回我不知所措的索引,以了解出于我的目的该做什么,b)boolean array indexing和c)boolean masks。我通常可以理解用于简单2d数组的每种方法,但是我很难理解这些方法之间的差异,并且无法让它们返回3d数组的正确值。
def real_size(arr3):
true_0 = []
true_1 = []
true_2 = []
print(f'The input array shape is: {arr3.shape}')
for zero_ in range (0, arr3.shape[0]):
if arr3[zero_].any()==True:
true_0.append(zero_)
for one_ in range (0, arr3.shape[1]):
if arr3[:,one_,:].any()==True:
true_1.append(one_)
for two_ in range (0, arr3.shape[2]):
if arr3[:,:,two_].any()==True:
true_2.append(two_)
arr4 = arr3[min(true_0):max(true_0) + 1, min(true_1):max(true_1) + 1, min(true_2):max(true_2) + 1]
print(f'The nonzero area is: {arr4.shape}')
return arr4
# Then use it on a small test array:
test_array = np.zeros([2, 3, 4], dtype = int)
test_array[0:2, 0:2, 0:2] = 1
#The function call works and prints out as expected:
non_zero = real_size(test_array)
>> The input array shape is: (2, 3, 4)
>> The nonzero area is: (2, 2, 2)
# So, the array is correct, but likely not the best way to get there:
non_zero
>> array([[[1, 1],
[1, 1]],
[[1, 1],
[1, 1]]])
代码工作正常,但是我在更大,更复杂的数组上使用它,因此认为这不是合适的方法。任何对采用更直接的方法进行这项工作的想法将不胜感激。如果输入数组例如在原始数组内有两个单独的非零3d区域,我也会担心错误和结果。
为澄清问题,我需要将一个或多个3D部分作为一个或多个3d数组(以原始的较大数组开头)返回。返回的数组不应在三维空间中任何给定的外部平面中包含无关的零(或假值)。仅获取非零值的索引(反之亦然)本身并不能解决问题。
答案 0 :(得分:2)
假设您要消除仅包含 零的所有行,列等,可以执行以下操作:
nz = (test_array != 0)
non_zero = test_array[nz.any(axis=(1, 2))][:, nz.any(axis=(0, 2))][:, :, nz.any(axis=(0, 1))]
使用np.nonzero
的替代解决方案:
i = [np.unique(_) for _ in np.nonzero(test_array)]
non_zero = test_array[i[0]][:, i[1]][:, :, i[2]]
这也可以推广到任意维度,但需要做更多的工作(此处仅显示第一种方法):
def real_size(arr):
nz = (arr != 0)
result = arr
axes = np.arange(arr.ndim)
for axis in range(arr.ndim):
zeros = nz.any(axis=tuple(np.delete(axes, axis)))
result = result[(slice(None),)*axis + (zeros,)]
return result
non_zero = real_size(test_array)