在numpy和python中快速删除重复项

pzo*_*pzo 6 python arrays optimization performance numpy

有没有快速的方法来获得numpy中的独特元素?我有类似的代码(最后一行)

tab = numpy.arange(100000000)

indices1 = numpy.random.permutation(10000)
indices2 = indices1.copy()
indices3 = indices1.copy()
indices4 = indices1.copy()

result = numpy.unique(numpy.array([tab[indices1], tab[indices2], tab[indices3], tab[indices4]]))
Run Code Online (Sandbox Code Playgroud)

这只是一个例子,在我的情况下indices1, indices2,...,indices4包含不同的索引集并具有各种大小.最后一行被执行多次并且Inoticed它实际上是我的代码中的瓶颈({numpy.core.multiarray.arange}作为先决条件).此外,排序并不重要,索引数组中的元素属于int32类型.我正在考虑使用带有元素值的哈希表作为键并尝试:

seq = itertools.chain(tab[indices1].flatten(), tab[indices2].flatten(), tab[indices3].flatten(), tab[indices4].flatten())
myset = {}
map(myset.__setitem__, seq, [])
result = numpy.array(myset.keys())
Run Code Online (Sandbox Code Playgroud)

但情况更糟.

有什么方法可以加快速度吗?我想性能损失来自复制数组的'花式索引',但我只需要读取结果元素(我不修改任何东西).

Bi *_*ico 3

抱歉,我不完全理解你的问题,但我会尽力提供帮助。

Fist {numpy.core.multiarray.arange} 是 numpy.arange 不是花哨的索引,不幸的是花哨的索引不会在分析器中显示为单独的行项目。如果你在循环中调用 np.arange ,应该看看是否可以将其移到外面。

In [27]: prun tab[tab]
     2 function calls in 1.551 CPU seconds

Ordered by: internal time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    1.551    1.551    1.551    1.551 <string>:1(<module>)
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler'    objects}

In [28]: prun numpy.arange(10000000)
     3 function calls in 0.051 CPU seconds

Ordered by: internal time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.047    0.047    0.047    0.047 {numpy.core.multiarray.arange}
    1    0.003    0.003    0.051    0.051 <string>:1(<module>)
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
Run Code Online (Sandbox Code Playgroud)

其次,我假设这tab不在np.arange(a, b)您的代码中,因为如果它是tab[index] == index + a,但我认为这只是为了您的示例。

第三,np.concatenate比np.array快10倍左右

In [47]: timeit numpy.array([tab[indices1], tab[indices2], tab[indices3], tab[indices4]])
100 loops, best of 3: 5.11 ms per loop

In [48]: timeit numpy.concatenate([tab[indices1], tab[indices2], tab[indices3],     tab[indices4]])
1000 loops, best of 3: 544 us per loop
Run Code Online (Sandbox Code Playgroud)

(np.concatenate 也给出一个 (4*n,) 数组,np.array 给出一个 (4, n) 数组,其中 n 是索引 [1-4] 的长度。后者仅在索引 1-4 时才起作用都是一样长的。)

最后,如果您能执行以下操作,您还可以节省更多时间:

indices = np.unique(np.concatenate((indices1, indices2, indices3, indices4)))
result = tab[indices]
Run Code Online (Sandbox Code Playgroud)

按此顺序执行操作会更快,因为您减少了需要在选项卡中查找的索引数量,但只有当您知道选项卡的元素是唯一的时,它才会起作用(否则即使索引也可能会在结果中重复)是独一无二的)。

希望有帮助