简体   繁体   English

Numpy 使用布尔数组进行索引

[英]Numpy indexing using an array of booleans

I have the following array which indicates whether or not to take a certain item:我有以下数组,指示是否接受某个项目:

import numpy as np

test_array = np.array([[0, 0, 1],
                       [1, 1, 0],
                       [1, 1, 1]])

The array I want to index is this one:我要索引的数组是这个:

classes = ['a', 'b', 'c']

This is what the result should be:结果应该是这样的:

[['c'], ['a', 'b'], ['a', 'b', 'c']]

How can this be done?如何才能做到这一点?


I would start with something like that:我会从这样的事情开始:

result = []
for row in test_array:
    partial_result = []
    for i in range(3):
        if row[i] == 1:
            partial_result.append(classes[i])
    result.append(partial_result)
print(result)

Results with:结果:

[['c'], ['a', 'b'], ['a', 'b', 'c']]

In Python, we prefer list comprehension over loops, so time to improve:在 Python 中,我们更喜欢列表理解而不是循环,所以需要改进:

print([[classes[i] for i, val in enumerate(row) if val] for row in test_array])

enumerate is an in-build function which takes an iterable object as a parameter and returns iterable of tuples (index, element) for all elements in the original iterable, so enumerate(row) will return (0, [0, 0, 1]), (1, [1, 1, 0]) and (2, [1, 1, 1]). enumerate是一个内置 function ,它采用可迭代的 object 作为参数并返回原始迭代中所有元素的元组(索引,元素)的迭代,因此enumerate(row)将返回 (0, [0, 0, 1] )、(1, [1, 1, 0]) 和 (2, [1, 1, 1])。

for i, val in enumerate(row) if val will work, because 1s are interpreted as True in Python and 0s as False . for i, val in enumerate(row) if val将起作用,因为在 Python 中1s被解释为True ,而0s被解释为False

[[classes[i] for i, val in enumerate(row) if val] for row in test_array]
^ create a list of elements based on some original list ------->^
 ^ each element of that list will be a list itself.
      ^ elements of that inner lists will be objects from classes list
              ^ for each pair (i, element) from enumerate(row) take this ith
                element, but just if val == 1 ^

You could do the following:您可以执行以下操作:

import numpy as np

test_array = np.array([[0, 0, 1],
                       [1, 1, 0],
                       [1, 1, 1]])

classes = ['a', 'b', 'c']

lookup = dict(enumerate(classes))
result = [[lookup[i] for i, e in enumerate(arr) if e] for arr in test_array]
print(result)

Output Output

[['c'], ['a', 'b'], ['a', 'b', 'c']]

I would do it as this:我会这样做:

result = []
for array in test_array:
     result.append([classes[i] for i,value in enumerate(array ) if value ])

In one line you can do:在一行中,您可以执行以下操作:

print ([[c for (x, c) in zip(l, classes) if x] for l in test_array])

The answers I've seen so far range from awkward to, quite frankly, baffling, so here is a straightforward solution.到目前为止,我看到的答案从尴尬到坦率地说,令人费解,所以这里有一个简单的解决方案。

import np

arr = np.array([[0, 0, 1], [1, 1, 0], [1, 1, 1]])

arr_bools = arr.astype(np.bool)

lookup_lst = np.array(['a', 'b', 'c'])

res = [lookup_lst[row].tolist() for row in arr_bools]

This can be done by matrix multiplication:这可以通过矩阵乘法来完成:

[*map(list, test_array.astype('O')@classes)]
# [['c'], ['a', 'b'], ['a', 'b', 'c']]

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

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