我有一个整数值为 1 或 0 的 Numpy 数组(必要时可以转换为 bool 值)。该数组是正方形和对称的(请参阅下面的注释),我想要一个出现 1 的索引列表:
请注意 array[i][j] == array[j][i]
和 array[i][i] == 0
通过设计。我也不能有任何重复。
import numpy as np
array = np.array([
[0, 0, 1, 0, 1, 0, 1],
[0, 0, 1, 1, 0, 1, 0],
[1, 1, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 1, 1, 0],
[1, 0, 0, 1, 0, 0, 1],
[0, 1, 0, 1, 0, 0, 0],
[1, 0, 1, 0, 1, 0, 0]
])
我想要这样的结果(每个子列表的顺序并不重要,子列表中每个元素的顺序也不重要):
[
[0, 2],
[0, 4],
[0, 6],
[1, 2],
[1, 3],
[1, 5],
[2, 6],
[3, 4],
[3, 5],
[4, 6]
]
要说明的另一点是,我不希望使用条件 j<i
遍历所有索引两次。因为我的数组的大小可能很大,但我知道这是可能的 - 我已经使用两个 for 循环编写了一个示例:
result = []
for i in range(array.shape[0]):
for j in range(i):
if array[i][j]:
result.append([i, j])
print(pd.DataFrame(result).sort_values(1).values)
# using dataframes and arrays for formatting but looking for
# 'result' which is a list
# Returns (same as above but columns are the opposite way round):
[[2 0]
[4 0]
[6 0]
[2 1]
[3 1]
[5 1]
[6 2]
[4 3]
[5 3]
[6 4]]
最佳答案
idx = np.argwhere(array)
idx = idx[idx[:,0]<idx[:,1]]
另一种方式:
idx = np.argwhere(np.triu(array))
输出:
[[0 2]
[0 4]
[0 6]
[1 2]
[1 3]
[1 5]
[2 6]
[3 4]
[3 5]
[4 6]]
比较:
#@bousof solution
def method1(array):
return np.vstack(np.where(np.logical_and(array, np.diff(np.ogrid[:array.shape[0],:array.shape[0]])[0]>=0))).transpose()[:,::-1]
#Also mentioned by @hpaulj
def method2(array):
return np.argwhere(np.triu(array))
def method3(array):
idx = np.argwhere(array)
return idx[idx[:,0]<idx[:,1]]
#The original method in question by OP(d-man)
def method4(array):
result = []
for i in range(array.shape[0]):
for j in range(i):
if array[i][j]:
result.append([i, j])
return result
#suggestd by @bousof in comments
def method5(array):
return np.vstack(np.where(np.triu(array))).transpose()
inputs = [np.random.randint(0,2,(n,n)) for n in [10,100,1000,10000]]
似乎 method1、method2 和 method5 对于大型数组来说稍微快一些,而 method3 对于较小的数组更快案例:
关于python - 如何使用 bool 型方形对称 numpy 数组中的真值存储存储索引对?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62839959/