numpy.unique保持顺序

68

1
请参阅numpy的此错误报告 - Nico Schlömer
7个回答

113

unique() 操作速度较慢,时间复杂度为 O(Nlog(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

O(N)的复杂度没有在任何地方提到,因此只是一种实现细节。文档仅说明它比numpy.unique显着更快,但这可能只意味着它具有较小的常数或复杂度可能介于线性和NlogN之间。 - Bakuriu
4
这里提到了:http://www.slideshare.net/fullscreen/wesm/a-look-at-pandas-design-and-development/41 - HYRY
1
你如何在 pandas.unique() 中保留顺序?据我所知,它不允许任何参数。 - F Lekschas
3
@F Lekschas,pandas.unique()默认情况下似乎保留了顺序。 - themachinist
2
@HYRY - 链接已损坏,需要删除“/fullscreen”:https://www.slideshare.net/wesm/a-look-at-pandas-design-and-development/41 - Alaa M.

27
使用`np.unique`函数的`return_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')

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

4
这只是已接受答案的较慢版本。 - Eric

4

如果您想要删除已排序可迭代对象中的重复项,可以使用 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解决问题比纯Python解决方案更快,因为numpy是专门针对此类问题进行优化的。 - jamylak

3
#List we need to remove duplicates from while preserving order

x = ['key1', 'key3', 'key3', 'key2'] 

thisdict = dict.fromkeys(x) #dictionary keys are unique and order is preserved

print(list(thisdict)) #convert back to list

output: ['key1', 'key3', 'key2']

2

如果您想删除重复的条目,就像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]

3
这只适用于数字。请使用“!=”代替“-”。 - Eric

2

使用OrderedDict(比列表解析更快)

from collections import OrderedDict  
a = ['b','a','b','a','a','c','c']
list(OrderedDict.fromkeys(a))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接