简体   繁体   English

如何获取numpy数组的非对角元素的索引?

[英]How to get indices of non-diagonal elements of a numpy array?

How to get indices of non-diagonal elements of a numpy array?如何获取numpy数组的非对角元素的索引?

a = np.array([[7412, 33, 2],
              [2, 7304, 83],
              [3, 101, 7237]])

I tried as follows:我尝试如下:

diag_indices = np.diag_indices_from(a)
print diag_indices
(array([0, 1, 2], dtype=int64), array([0, 1, 2], dtype=int64))

After that, no idea... The expected result should be:在那之后,不知道......预期的结果应该是:

result = [[False, True, True],
        [True, False, True],
         [True, True, False]]

To get the mask, you can use np.eye , like so -要获得面具,你可以使用np.eye ,像这样 -

~np.eye(a.shape[0],dtype=bool)

To get the indices, add np.where -要获取索引,请添加np.where -

np.where(~np.eye(a.shape[0],dtype=bool))

Sample run -样品运行 -

In [142]: a
Out[142]: 
array([[7412,   33,    2],
       [   2, 7304,   83],
       [   3,  101, 7237]])

In [143]: ~np.eye(a.shape[0],dtype=bool)
Out[143]: 
array([[False,  True,  True],
       [ True, False,  True],
       [ True,  True, False]], dtype=bool)

In [144]: np.where(~np.eye(a.shape[0],dtype=bool))
Out[144]: (array([0, 0, 1, 1, 2, 2]), array([1, 2, 0, 2, 0, 1]))

There are few more ways to get such a mask for a generic non-square input array.对于通用非方形输入数组,还有其他几种方法可以获得这样的掩码。

With np.fill_diagonal -使用np.fill_diagonal -

out = np.ones(a.shape,dtype=bool)
np.fill_diagonal(out,0)

With broadcasting -随着broadcasting -

m,n = a.shape
out = np.arange(m)[:,None] != np.arange(n)
>>> import numpy as np
>>> a = np.array([[7412, 33, 2],
...               [2, 7304, 83],
...               [3, 101, 7237]])
>>> non_diag = np.ones(shape=a.shape, dtype=bool) - np.identity(len(a)).astype(bool)
>>> non_diag
array([[False,  True,  True],
       [ True, False,  True],
       [ True,  True, False]], dtype=bool)

As an additional idea to previous answers, you could select the indices of the upper and lower triangles :作为先前答案的另一个想法,您可以选择上下三角形的索引:

a = np.array([[7412, 33, 2],
              [2, 7304, 83],
              [3, 101, 7237]])
# upper triangle. k=1 excludes the diagonal elements.
xu, yu = np.triu_indices_from(a, k=1)
# lower triangle
xl, yl = np.tril_indices_from(a, k=-1)  # Careful, here the offset is -1

# combine
x = np.concatenate((xl, xu))
y = np.concatenate((yl, yu))

As described in the doc , you can then use those to index and assign values:文档中所述,您可以使用它们来索引和分配值:

out = np.ones((3,3), dtype=bool)
out[(x, y)] = False

gives:给出:

>>> out
array([[ True, False, False],
   [False,  True, False],
   [False, False,  True]])

To extend @PlasmaBinturong's and @Divakar's answers, you could use advanced indexing based on np.triu_indices and np.tril_indices :要扩展@PlasmaBinturong 和@Divakar 的答案,您可以使用基于np.triu_indicesnp.tril_indices的高级索引:

triu_idx = np.triu_indices(len(a), k=1) #finding advanced indices of upper right triangle
tril_idx = np.tril_indices(len(a), k=-1) #finding advanced indices of lower left triangle
out = np.ones(a.shape, dtype=bool)
out[triu_idx] = False #padding upper right triangle with zeros
out[tril_idx] = False #padding upper left triangle with zeros
>>> out
array([[ True, False, False],
       [False,  True, False],
       [False, False,  True]])
  • triu_idx = np.triu_indices(len(a), k=1) is a shorthand for np.nonzero(np.less.outer(np.arange(len(a)), np.arange(len(a)))) triu_idx = np.triu_indices(len(a), k=1)np.nonzero(np.less.outer(np.arange(len(a)), np.arange(len(a))))的简写

  • np.tril_indices(len(a), k=-1) is a shorthand for np.nonzero(np.greater.outer(np.arange(len(a)), np.arange(len(a)))) np.tril_indices(len(a), k=-1)np.nonzero(np.greater.outer(np.arange(len(a)), np.arange(len(a))))的简写

So instead of np.less.outer(...) & np.greater.outer(...) you could use:所以代替np.less.outer(...) & np.greater.outer(...)你可以使用:

>>> np.not_equal.outer(np.arange(len(a)), np.arange(len(a)))
array([[False,  True,  True],
       [ True, False,  True],
       [ True,  True, False]])

which could be replaced by Syntactic Sugar in @Divakar's solution: np.arange(len(a))[:, None] != np.arange(len(a))在@Divakar 的解决方案中可以用语法糖代替: np.arange(len(a))[:, None] != np.arange(len(a))

This is an output desired but besides that, let's plug it into a previous code to compare with the previous process:这是所需的输出,但除此之外,让我们将其插入之前的代码中以与之前的过程进行比较:

out = np.ones(a.shape, dtype=bool)
idx = np.not_equal.outer(np.arange(len(a)), np.arange(len(a))) # you need only this
tri_both = np.nonzero(idx)
out[tri_both] = False
>>> out
array([[False,  True,  True],
       [ True, False,  True],
       [ True,  True, False]])

Conclusion .结论 Don't convert boolean indices to numerical ones and then back.不要将布尔索引转换为数字索引,然后再返回。 This is inefficient as to compare with working on boolean indices straight.与直接处理布尔索引相比,这是低效的。

import numpy as np
a = np.array([[7412, 33, 2],
              [2, 7304, 83],
              [3, 101, 7237]])
np.invert(np.eye(a.shape[0], dtype=bool))

gives

array([[False,  True,  True],
       [ True, False,  True],
       [ True,  True, False]])

When a Boolean diagonal matrix is inverted, off-diagonal terms become True while the diagonal terms are False.当布尔对角矩阵反转时,非对角项变为 True,而对角项为 False。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM