numpy:内容索引,内容索引

时间:2018-04-24 15:29:51

标签: python arrays numpy indexing

我的问题是关于Numpy数组的索引内容,内容索引。 有没有高效优雅的方式?

从这个(一维,百万价值):

a = np.array ([0,1,1,1,3,3,5,1,2,3,6,9,10,....]) 

列出或ndarray:

output = [[0],[1,2,3,7],[8],[4,5,9],[],[6],[10],[],[],[11],[12],....]

output[0] = value 0 , result:[0]       = locatoin 0 in a 
output[1] = value 1 , result:[1,2,3,7] = location 1 ,2 ,3 , 7 in a
output[2] = value 2 , result:[8] = location 8 
output[3] = value 3 , result:[4,5,9] = location 4,5,9 
output[4] = value 4 , result:[] = location nothing
........

4 个答案:

答案 0 :(得分:1)

我无法想象没有完全循环的解决方案,但是一个可行的解决方案涉及使用where函数。我已经在随机整数列表中对它进行了测试,而且速度非常快。

import numpy as np

a = np.array([0,1,1,1,3,3,5,1,2,3,6,9,10]) 

output = [np.where(a == x)[0] if x in a else [] for x in range(a.min(), a.max())]

在这里你得到output=

[array([0]),
 array([1, 2, 3, 7]),
 array([8]),
 array([4, 5, 9]),
 [],
 array([6]),
 array([10]),
 [],
 [],
 array([11])]

答案 1 :(得分:1)

由于您正在处理1D数组 * ,您可以使用广播将您的数组与其唯一项目进行比较,以找到所需的位置。

In [68]: a = np.array ([0,1,1,1,3,3,5,1,2,3,6,9,10, 10, 9, 9]) 

In [69]: arr = np.unique(a)

In [70]: x, y= np.where(arr[:,None] == a)

In [71]: inds = np.where(x[:-1] - x[1:] != 0)[0] + 1

In [72]: np.split(y, inds)
Out[72]: 
[array([0]),
 array([1, 2, 3, 7]),
 array([8]),
 array([4, 5, 9]),
 array([6]),
 array([10]),
 array([11, 14, 15]),
 array([12, 13])]

如果真的有必要找到错过的项目,虽然它不清楚你的预期输出背后的逻辑是什么,但似乎你找到所有的指数a.min()a.max()之间的商品。在这种情况下,您可以使用np.arange(a.min(), a.max())作为arr,然后将arr[:,None] == a放入掩码中,然后您可以找到错过的项目的索引,如下所示:

In [115]: missed = np.where((~mask).all(1))[0]

In [116]: missed
Out[116]: array([4, 7, 8])

<子> *来自documentation:对于三维数组,这在代码行方面肯定是高效的,并且对于小数据集,它也可以在计算上有效。但是,对于大型数据集,创建大型3-d阵列可能会导致性能低下。 此外,广播是一种强大的工具,用于编写简短且通常直观的代码,可以在C中非常有效地进行计算。但是,有时广播会为特定算法使用不必要的大量内存。在这些情况下,最好在Python中编写算法的外部循环。这也可能产生更易读的代码,因为随着广播中维度的数量增加,使用广播的算法往往变得更难以解释。

答案 2 :(得分:1)

你可以这样使用scipy.sparse

>>> from scipy import sparse
>>>
>>> def enum_loc_per_val(a):
...     x = sparse.csr_matrix((np.ones(a.shape, dtype=np.int8), a, np.arange(a.size+1))).tocsc()
...     return np.split(x.indices, x.indptr[1:-1])
... 
>>> 
>>> enum_loc_per_val(a)
[array([0], dtype=int32), array([1, 2, 3, 7], dtype=int32), array([8], dtype=int32), array([4, 5, 9], dtype=int32), array([], dtype=int32), array([6], dtype=int32), array([10], dtype=int32), array([], dtype=int32), array([], dtype=int32), array([11], dtype=int32), array([12], dtype=int32)]

答案 3 :(得分:1)

直接的Python解决方案是在字典中收集值:

In [181]: dd = {i:[] for i in range(0,11)}
In [182]: a = np.array([0,1,1,1,3,3,5,1,2,3,6,9,10]) 
In [183]: for i,v in enumerate(a.tolist()):
     ...:     dd[v].append(i)
     ...:     
In [184]: dd
Out[184]: 
{0: [0],
 1: [1, 2, 3, 7],
 2: [8],
 3: [4, 5, 9],
 4: [],
 5: [6],
 6: [10],
 7: [],
 8: [],
 9: [11],
 10: [12]}

如果您不关心[]个案,则可以使用collections.defaultdictionary

我建议使用tolist(),因为列表上的迭代比数组上的迭代更快。但是,这一步是否有助于整体时间,我不知道。这类问题需要时间测试。

我确定之前有这样的问题;我依旧记得在过去的半年里回答了一个问题。但是搜索将比写这个答案花费更长的时间。