2012-10-17 12 views
16

Wie kann ich numpy verwenden einzigartig, ohne das Ergebnis Sortier aber nur in der Reihenfolge, wie sie in der Reihenfolge erscheinen? Etwas wie das?numpy einzigartig ohne Art

a = [4,2,1,3,1,2,3,4]

np.unique(a) = [4,2,1,3]

statt

np.unique(a) = [1,2,3,4]

sollte Gebrauch naive Lösung fein sein, eine einfache Funktion zu schreiben. Aber wie ich dies mehrere Male tun müssen, gibt es eine schnelle und saubere Art und Weise, dies zu tun?

Antwort

30

Sie können dies mit dem return_index Parameter:

 
>>> import numpy as np 
>>> a = [4,2,1,3,1,2,3,4] 
>>> np.unique(a) 
array([1, 2, 3, 4]) 
>>> indexes = np.unique(a, return_index=True)[1] 
>>> [a[index] for index in sorted(indexes)] 
[4, 2, 1, 3] 
+0

immer hilfreich, um die Dokumente zu verlinken: [numpy.unique] (https://docs.scipy.org/doc/numpy-1.13.0/ reference/generated/numpy.unique.html) – BoltzmannBrain

+0

Ja das bekommt die eindeutigen Indizes, aber ist das Sortieren notwendig? Die Iterationen erforderl zu sortieren sind die gleichen wie nur für einzigartige Gegenstände durch die Anordnung der Suche, so dass die Zeitkomplexität nicht vermieden werden kann. Aber numpy.unique gibt ein neues Array-Objekt zurück. Wir sollten diese räumliche Komplexität vermeiden können. – BoltzmannBrain

4

du durch so etwas wie dies tun numpy mit tun könnte, ist die mergsort stabil, so es wird Ihnen die erste oder letzte Vorkommen herausgreifen lassen von jeder Wert:

def unique(array, orderby='first'): 
    array = np.asarray(array) 
    order = array.argsort(kind='mergesort') 
    array = array[order] 
    diff = array[1:] != array[:-1] 
    if orderby == 'first': 
     diff = np.concatenate([[True], diff]) 
    elif orderby == 'last': 
     diff = np.concatenate([diff, [True]]) 
    else: 
     raise ValueError 
    uniq = array[diff] 
    index = order[diff] 
    return uniq[index.argsort()] 

Diese Antwort ist sehr ähnlich:

def unique(array): 
    uniq, index = np.unique(array, return_index=True) 
    return uniq[index.argsort()] 

Aber, numpy.unique verwendet intern eine unstable Sortierung, so dass nicht garantiert wird, dass ein bestimmter Index (erster oder letzter) erhalten wird.

Ich denke, eine geordnete dict könnte auch funktionieren:

def unique(array): 
    uniq = OrderedDict() 
    for i in array: 
     uniq[i] = 1 
    return uniq.keys() 
+0

Vielen Dank für Ihre schnelle Antwort. Ich habe darüber nachgedacht, die ersten, aber ich bin nicht sicher, ob es die schnellste ist. Der zweite Fehler sollte darin bestehen, implizit ein numpiges Objekt in ein Python-Objekt zu schreiben :) – kuantkid

+0

Ist das Problem mit dem zweiten 'unique' mit' np.unique's 'return_index' Argument, dass es zu falschen Ergebnissen führen könnte? Dass diese "unique" eine Sequenz mit einigen Elementen zurückgibt, die nicht der Reihenfolge entsprechen, die durch die ursprüngliche Sequenz auferlegt wird, z. B. (rein zur Demonstration) 'unique ([1,0,1]) -> [0,1]'? –

+0

'np.unique's Dokumentation (http://docs.scipy.org/doc/numpy/reference/generated/numpy.unique.html) besagt, dass die Indizes, die mit' return_index = True 'zurückgegeben werden, das * zuerst anzeigen * Vorkommen, also sollte dein zweites 'einzigartiges' sicher und korrekt sein, oder? –