2013-03-26 13 views

risposta

33

unique() è lento, O (nlog (N)), ma è possibile effettuare questa operazione seguente codice:

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

uscita:

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

Pandas.unique() è molto più veloce per grande array 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

La complessità 'O (N)' non è menzionata ovunque ed è quindi solo un dettaglio di implementazione. La documentazione afferma semplicemente che è * significativamente più veloce di 'numpy.unique' *, ma questo può semplicemente significare che ha costanti più piccole o la complessità potrebbe essere tra lineare e NlogN. – Bakuriu

+3

È menzionato qui: http://www.slideshare.net/fullscreen/wesm/a-look-at-pandas-design-and-development/41 – HYRY

+0

Come manterresti l'ordinamento con 'pandas.unique()'? Per quanto posso dire, non consente alcun parametro. –

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

questo è solo un versione più lenta della risposta accettata – Eric

14

Utilizzare la funzionalità di return_indexnp.unique. Ciò restituisce gli indici in cui gli elementi si sono verificati per la prima volta nell'input. Quindi argsort quegli indici.

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

Se stai cercando di rimuovere la duplicazione di un già iterabile ordinato, è possibile utilizzare la funzione itertools.groupby:

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

Questo funziona più come comando UNIX 'uniq', poiché presuppone che la lista è già ordinato. Quando si tenta che nella lista non ordinata si otterrà qualcosa di simile:

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

Quasi sempre i problemi di 'numpy' vengono risolti più velocemente usando' numpy', le soluzioni di python pure saranno lente dato che 'numpy' è specializzato. – jamylak

1

Se si desidera eliminare le voci ricorrenti, come lo strumento Unix uniq, questa è una soluzione:

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

Funziona solo per i numeri. Usa '! =' Invece di '-' – Eric

Problemi correlati