2013-03-26 16 views

Odpowiedz

33

unique() jest powolny, O (nlog (n)), ale można to zrobić poprzez następujący kod:

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)] 

wyjściowa:

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

Pandas.unique() jest znacznie szybsze na duże tablica 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

Złożoność 'O (N)' nie jest nigdzie wymieniana, a zatem jest jedynie szczegółem implementacji. Dokumentacja po prostu stwierdza, że ​​jest * znacznie szybsza niż "numpy.unique" *, ale może to po prostu oznaczać, że ma mniejsze stałe lub złożoność może być pomiędzy liniowym a NlogN. – Bakuriu

+3

Jest to wspomniane tutaj: http://www.slideshare.net/fullscreen/wesm/a-look-at-pandas-design-and-development/41 – HYRY

+0

Jak zachowałbyś porządek z 'pandas.unique()'? O ile mogę powiedzieć, nie pozwala żadnych parametrów. –

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

To tylko wolniejsza wersja zaakceptowanej odpowiedzi – Eric

14

Użyj funkcji return_index z np.unique. To zwraca indeksy, w których elementy pojawiły się po raz pierwszy na wejściu. Następnie te indeksy są 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

Jeśli próbujesz usunąć powielania i tak już klasyfikowane iterable można użyć itertools.groupby funkcję:

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

To działa bardziej jak polecenia UNIX „uniq”, ponieważ zakłada, że ​​lista jest już posortowana. Podczas próby go na niesegregowanych listy otrzymasz coś takiego:

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

Prawie przez cały czas problemy z 'numpy' są rozwiązywane szybciej niż" numpy ", a czyste rozwiązania Pythona będą powolne, ponieważ' numpy' jest wyspecjalizowany. – jamylak

1

Jeśli chcesz usunąć powtarzające się wpisy, jak narzędzia Unix uniq, jest to rozwiązanie:

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

Działa to tylko dla liczb. Użyj '! =' Zamiast '-' – Eric