Skip to main content
 首页 » 编程设计

python之不可广播的输出操作数 numpy 2D 转换为 3D

2025年05月04日13Leo_wl

在 NumPy 中,

    foo = np.array([[i+10*j for i in range(10)] for j in range(3)]) 
    array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9], 
           [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], 
           [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]]) 
    filter = np.nonzero(foo > 100)#nothing matches 
 
    foo[:,filter] 
    array([], shape=(3, 2, 0), dtype=int64) 
 
    foo[:,0:0] 
    array([], shape=(3, 0), dtype=int64) 
 
filter2 = np.nonzero(np.sum(foo,axis=0) < 47) 
foo[:,filter2] 
array([[[ 0,  1,  2,  3,  4,  5]], 
 
       [[10, 11, 12, 13, 14, 15]], 
 
       [[20, 21, 22, 23, 24, 25]]]) 
foo[:,filter2].shape 
(3, 1, 6) 

我有一个“过滤器”条件,我想对所有匹配列的所有行执行操作,但如果过滤器是空数组,我的 foo[:,filter] 会以某种方式广播到 3D 数组中。另一个例子是 filter2 -> 再次,当我期待 foo[:,(np.sum(foo,axis=0) < 47)] 的结果时,foo[:,filter2] 给了我一个 3D 数组

有人可以解释一下 np.nonzero 的正确用例与使用 bool 值查找正确的列/索引相比有哪些吗?

请您参考如下方法:

首先,当 filter 是 bool 数组时,foo[filter] == foo[filter.nonzero()]。

要理解为什么会得到意想不到的结果,您必须了解一下 python 如何进行索引。要在 python 中进行多维索引,您可以使用 [] 中的索引,以逗号分隔或使用元组。所以 foo[1, 2, 3] 与 foo[(1, 2, 3)] 相同。考虑到这一点,看看当您执行 foo[:, something] 时会发生什么。我相信在你的例子中你试图得到 foo[:, something[0], something[1]],但是你却得到了 foo[(slice[None], (something[ 0], something[1]))].

这有点学术性,因为如果您只是使用 filter 进行索引,您可能不需要使用非零值,只需使用 bool 数组作为索引,但如果需要,你可以这样做:

foo[:, filter[0]] 
 
# OR 
index = (slice(None),) + filter.nonzero() 
foo[index]