2013-03-26 2 views
22
['b','b','b','a','a','c','c'] 

numpy.unique даетnumpy.unique с заказом сохранены

['a','b','c'] 

Как я могу получить исходный порядок сохранился

['b','a','c'] 

Большие ответы. Бонусный вопрос. Почему ни один из этих методов не работает с данным набором данных? http://www.uploadmb.com/dw.php?id=1364341573 Вот вопрос numpy sort wierd behavior

ответ

33

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 
+0

Сложность «O (N)» нигде не упоминается и, таким образом, является только деталью реализации. В документации просто указано, что она значительно быстрее, чем 'numpy.unique' *, но это может просто означать, что она имеет меньшие константы или сложность может быть между линейными и NlogN. – Bakuriu

+3

Это упоминается здесь: http://www.slideshare.net/fullscreen/wesm/a-look-at-pandas-design-and-development/41 – HYRY

+0

Как бы сохранить заказ с помощью 'pandas.unique()'? Насколько я могу судить, это не позволяет никаких параметров. –

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

Это просто более медленная версия принятого ответа – Eric

14

Используйте return_index функциональность np.unique. Это возвращает индексы, в которых элементы сначала попадали на вход. Затем 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

Если вы пытаетесь устранить дублирование в уже отсортированный Iterable, вы можете использовать функцию 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

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