2013-03-26 124 views

回答

33

unique()是缓慢的,O(n日志(N)),但您可以通过下面的代码做到这一点:

import numpy as np 
a = np.array(['b','a','b','b','d','a','a','c','c']) 
_, idx = np.unique(a, return_index=True) 
print a[np.sort(idx)] 

输出:

['b' 'a' 'd' 'c'] 

Pandas.unique()是快得多大阵列O(N):

import pandas as pd 

a = np.random.randint(0, 1000, 10000) 
%timeit np.unique(a) 
%timeit pd.unique(a) 

1000 loops, best of 3: 644 us per loop 
10000 loops, best of 3: 144 us per loop 
+0

“O(N)”复杂性在任何地方都没有提及,因此只是一个实现细节。该文档简单地表明它比'numpy.unique' *快得多,但这可能仅仅意味着它具有较小的常量或复杂度可能介于线性和NlogN之间。 – Bakuriu 2013-03-26 17:57:39

+3

它在这里提到:http://www.slideshare.net/fullscreen/wesm/a-look-at-pandas-design-and-development/41 – HYRY 2013-03-26 22:40:26

+0

你将如何保留与'pandas.unique()'的顺序?据我可以告诉它不允许任何参数。 – 2016-11-23 17:02:33

7
a = ['b','b','b','a','a','c','c'] 
[a[i] for i in sorted(np.unique(a, return_index=True)[1])] 
+0

这仅仅是一个接受的答案的较慢版本 – Eric 2017-02-16 14:30:19

14

使用的np.uniquereturn_index功能。这将返回元素首次出现在输入中的索引。然后argsort那些指数。

>>> u, ind = np.unique(['b','b','b','a','a','c','c'], return_index=True) 
>>> u[np.argsort(ind)] 
array(['b', 'a', 'c'], 
     dtype='|S1') 
1

如果你想删除的已排序可迭代重复,您可以使用itertools.groupby功能:

>>> from itertools import groupby 
>>> a = ['b','b','b','a','a','c','c'] 
>>> [x[0] for x in groupby(a)] 
['b', 'a', 'c'] 

这更象UNIX“uniq的”命令,因为它假设列表已经排序。当你尝试无序列表中你会得到这样的事情:

>>> b = ['b','b','b','a','a','c','c','a','a'] 
>>> [x[0] for x in groupby(b)] 
['b', 'a', 'c', 'a'] 
+2

几乎所有'numpy'问题都可以通过'numpy'解决得更快,纯粹的Python解决方案将会很慢,因为'numpy'是专业化的。 – jamylak 2013-03-26 13:09:15

1

如果要删除重复项,像Unix工具uniq,这是一个解决方案:

def uniq(seq): 
    """ 
    Like Unix tool uniq. Removes repeated entries. 
    :param seq: numpy.array 
    :return: seq 
    """ 
    diffs = np.ones_like(seq) 
    diffs[1:] = seq[1:] - seq[:-1] 
    idx = diffs.nonzero() 
    return seq[idx] 
+1

这只适用于数字。使用'!='而不是'-' – Eric 2017-02-16 14:31:22