是否有可能找到包含给定值的 2D numpy 数组(不是)的第 0 个索引位置?

Is it possible to find the 0th index-position of a 2D numpy array (not) containing a given vaule?

是否可以找到包含给定值的 2D numpy 数组(不是)的第 0 个索引位置?

我想要的,期待的

我有一个包含整数的二维 numpy 数组。我的目标是找到不包含给定值的数组的索引(使用 numpy 函数)。这是这样一个数组的示例,名为 ortho_disc:

>>> ortho_disc 
Out: [[1 1 1 0 0 0 0 0 0]
      [1 0 1 1 0 0 0 0 0]
      [0 0 0 0 0 0 2 2 0]]

如果我希望找到不包含 2 的数组,我希望输出 [0, 1],因为 ortho_disc 的第一个和第二个数组不包含值 2。

我试过的

我调查了 np.argwherenp.nonzeronp.isinnp.where,但没有得到预期的结果。我使用 np.where 的最佳尝试如下:

>>> np.where(2 not in ortho_disc, [True]*3, [False]*3) 
Out: [False False False]

但它没有 return 预期的 [True, True, False]。这在我们查看输出 ortho_disc 自己评估的数组后尤其奇怪:

>>> 2 not in ortho_disc[0] 
Out: True

>>> 2 not in ortho_disc[1] 
Out:True

>>> 2 not in ortho_disc[2]
Out: False

使用 argwhere

使用np.argwhere,我得到的只是一个空数组(不是预期的[0, 1]):

>>> np.argwhere(2 not in ortho_disc) 
Out: []

我怀疑这是因为 numpy 首先压平 ortho_disc,然后检查 2 not in ortho_disc 的真值? 使用 np.nonzero(2 not in ortho_disc).

对同一个空数组进行 returned

我的代码

import numpy as np
ortho_disc = np.array([[1, 1, 1, 0, 0, 0, 0, 0, 0],
                       [1, 0, 1, 1, 0, 0, 0, 0, 0],
                       [0, 0, 0, 0, 0, 0, 2, 2, 0,]])
polymer = 2

print(f'>>> ortho_disc \nOut:\n{ortho_disc}\n')
print(f'>>> {polymer} not in {ortho_disc[0]} \nOut: {polymer not in ortho_disc[0]}\n')
print(f'>>> {polymer} not in {ortho_disc[1]} \nOut: {polymer not in ortho_disc[1]}\n')
print(f'>>> {polymer} not in {ortho_disc[2]} \nOut: {polymer not in ortho_disc[2]}\n\n')

breakpoint = np.argwhere(polymer not in ortho_disc)
print(f'>>>np.argwhere({polymer} not in ortho_disc) \nOut: {breakpoint}\n\n\n')

输出:

>>> ortho_disc 
Out:
[[1 1 1 0 0 0 0 0 0]
 [1 0 1 1 0 0 0 0 0]
 [0 0 0 0 0 0 2 2 0]]

>>> 2 not in [1 1 1 0 0 0 0 0 0] 
Out: True

>>> 2 not in [1 0 1 1 0 0 0 0 0] 
Out: True

>>> 2 not in [0 0 0 0 0 0 2 2 0] 
Out: False


>>>np.argwhere(2 not in ortho_disc) 
Out: []

预期输出

从下面两行开始:

breakpoint = np.argwhere(polymer not in ortho_disc)
print(f'>>>np.argwhere({polymer} not in ortho_disc) \nOut: {breakpoint}\n\n\n')

我期待以下输出:

>>>np.argwhere(2 not in ortho_disc) 
Out: [0, 1]

总结

我真的很想得到关于如何解决这个问题的反馈,因为多年来我一直在为这个看似简单的问题绞尽脑汁。正如我提到的,重要的是要避免 ortho_disc 上明显的 'easy-way-out' 循环,最好使用 numpy。

提前致谢!

In [13]: ortho_disc
Out[13]: 
array([[1, 1, 1, 0, 0, 0, 0, 0, 0],
       [1, 0, 1, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 2, 2, 0]])

In [14]: polymer = 2

In [15]: (ortho_disc != polymer).all(axis=1).nonzero()[0]
Out[15]: array([0, 1])

分解:ortho_disc != polymer 是一个布尔值数组:

In [16]: ortho_disc != polymer
Out[16]: 
array([[ True,  True,  True,  True,  True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True,  True, False, False,  True]])

我们希望所有行都为 True;为此,我们可以沿轴 1(即沿行)应用 all() 方法:

In [17]: (ortho_disc != polymer).all(axis=1)
Out[17]: array([ True,  True, False])

这是不包含 polymer 的行的布尔掩码。

使用nonzero()查找不为0的值的索引(True被认为是非零,False被认为是0):

In [19]: (ortho_disc != polymer).all(axis=1).nonzero()
Out[19]: (array([0, 1]),)

注意nonzero()返回了一个长度为1的元组;通常,它 returns 一个长度与数组维数相同的元组。这里的输入数组是一维的。通过使用 [0]:

进行索引从元组中提取所需的结果
In [20]: (ortho_disc != polymer).all(axis=1).nonzero()[0]
Out[20]: array([0, 1])

您可以为此使用 numpy 广播。 ortho_disc == 2 将 return 数组的掩码,其中如果数组中的值不是 2,则每个值为 True,如果是 2,则为 False。然后,使用 np.allaxis=1 将每一行压缩为一个布尔值,指示该行是否仅包含真值(真值 = 没有 2):

>>> np.all(ortho_disc != 2, axis=1)
array([ True,  True, False])

如果你想得到索引,只需 np.where 上面的内容:

>>> np.where(np.all(ortho_disc != 2, axis=1))[0]
array([0, 1])