2017-03-12 3 views
0

Meine Datenproben sind jeweils ein numpy Array von Form, z. (100, 100, 9), und ich habe 10 von diesen in einer einzigen Anordnung foo der Form (10, 100, 100, 9) verkettet. Über die 10 Datenproben möchte ich die Indizes der Wiederholungswerte finden. Also zum Beispiel, wenn foo[0, 42, 42, 3] = 0.72 und foo[0, 42, 42, 7] = 0.72, ich möchte eine Ausgabe, die dies widerspiegelt. Was ist ein effizienter Weg?Suchen Sie sich wiederholende Werte im Array numpy

Ich denke an ein boolesches Ausgabe-Array von Shape (100, 100, 9), aber gibt es einen besseren Ansatz als das Schleifen jedes Datenbeispiels zu vergleichen (quadratische Laufzeit für die Anzahl der Datenproben (10))?

+0

Möchten Sie nur einen Wert markieren, der ein Duplikat enthält, oder möchten Sie ein Wörterbuch mit Datenwerten als Schlüssel und Indizes als Wörterbuchwerte duplizieren? – James

+0

@James die Frage wurde generische nicht angegeben, die genaue Daten zurückgegeben, um die möglichen Lösungen nicht einzuschränken, aber ich denke, ein Boolean-Array, das die Duplikate einfach per Index markiert (wie oben vorgeschlagen). – BoltzmannBrain

Antwort

0

Im folgenden Schnipsel ist dups das gewünschte Ergebnis: Ein Boolescher Array, das zeigt, welche Indizes Duplikate sind. Es gibt auch einen delta Schwellenwert, so dass jeder Unterschied in den Werten < = dieser Schwellenwert ein Duplikat ist.

-1

Hier ist eine Lösung mit argsort für jede Probe. Nicht schön, nicht schnell, aber macht den Job.

import numpy as np 
from timeit import timeit 

def dupl(a, axis=0, make_dict=True): 
    a = np.moveaxis(a, axis, -1) 
    i = np.argsort(a, axis=-1, kind='mergesort') 
    ai = a[tuple(np.ogrid[tuple(map(slice, a.shape))][:-1]) + (i,)] 
    same = np.zeros(a.shape[:-1] + (a.shape[-1]+1,), bool) 
    same[..., 1:-1] = np.diff(ai, axis=-1) == 0 
    uniqs = np.where((same[..., 1:] & ~same[..., :-1]).ravel())[0] 
    same = (same[...,1:]|same[...,:-1]).ravel() 
    reps = np.split(i.ravel()[same], np.cumsum(same)[uniqs[1:]-1]) 
    grps = np.searchsorted(uniqs, np.arange(0, same.size, a.shape[-1])) 
    keys = ai.ravel()[uniqs] 
    if make_dict: 
     result = np.empty(a.shape[:-1], object) 
     result.ravel()[:] = [dict(zip(*p)) for p in np.split(
       np.array([keys, reps], object), grps[1:], axis=-1)] 
     return result 
    else: 
     return keys, reps, grps 

a = np.random.randint(0,10,(10,100,100,9)) 
axis = 0 
result = dupl(a, axis) 

print('shape, axis, time (sec) for 10 trials:', 
     a.shape, axis, timeit(lambda: dupl(a, axis=axis), number=10)) 
print('same without creating dict:', 
     a.shape, axis, timeit(lambda: dupl(a, axis=axis, make_dict=False), 
          number=10)) 

#check 
print("checking result") 
am = np.moveaxis(a, axis, -1) 
for af, df in zip(am.reshape(-1, am.shape[-1]), result.ravel()): 
    assert len(set(af)) + sum(map(len, df.values())) == len(df) + am.shape[-1] 
    for k, v in df.items(): 
     assert np.all(np.where(af == k)[0] == v) 
print("no errors") 

Drucke:

shape, axis, time (sec) for 10 trials: (10, 100, 100, 9) 0 5.328339613042772 
same without creating dict: (10, 100, 100, 9) 0 2.568383438978344 
checking result 
no errors 
+0

Es gibt Gerüche über den ganzen Code hinweg, und es gibt so viele verschiedene Sortierungen, dass es so aussieht, als ob es ineffizient ist. – BoltzmannBrain

+0

@BoltzmannBrain Bit hart, denkst du nicht? Im Gegensatz zu Ihnen hat dies eine vernünftige Komplexität, nicht O (n k^2), sondern O (n (log n/k + k log k)). Es ist nicht leicht für das Auge, das gebe ich zu, aber drehe es nicht, nur weil es jenseits von dir ist. –

Verwandte Themen