我的问题是关于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
........
答案 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()
,因为列表上的迭代比数组上的迭代更快。但是,这一步是否有助于整体时间,我不知道。这类问题需要时间测试。
我确定之前有这样的问题;我依旧记得在过去的半年里回答了一个问题。但是搜索将比写这个答案花费更长的时间。