2017-02-24 3 views
-1

Ich bin neu in Python, so kann ich etwas falsch machen. Lass mich zuerst erklären, was ich will.Argsort auf numpy.array als Generator

Ich habe eine große 1D numpy.array mit einigen Werten und ich muss die Indizes der ersten n kleinsten Werte kennen. Ich brauche sie für spätere Berechnungen. Natürlich kann ich einfach etwas tun wie ind = numpy.argsort(hugearray)[:n].

Das Problem ist, dass ich vorher nicht weiß, wie viele Indizes ich brauche, meine Berechnungen sind iterativ und holen eins nach dem anderen Index, bis es genug für die Berechnung gibt.

Eine andere Sache ist, dass ich einen faulen Argsort haben möchte, um zu vermeiden, neue ganze Reihe von argsorted Werten zu schaffen und unnötige Suche zu verhindern, also dachte ich an einen Generator. Aber ich weiß wirklich nicht, wie man es mit einem numpy.array macht.

UPD: aus hpaulj Antwort, habe ich versucht, einen Generator zu erstellen:

def gargsort(arr): 
    arr=arr.copy() 
    for i in range(len(arr)): 
     k = np.argmin(arr) 
     arra[k] = np.iinfo(arr[k]).max 
     yield k 

Kann sein, es ist möglich, es besser zu machen?

+1

Mathematisch müssen Sie das gesamte Array sortieren, um die kleinsten Elemente zu kennen? –

+0

'np.argpartition (hugearray, n) [: n]' gibt die gleichen Indizes zurück, aber in einer unsortierten Reihenfolge. Es ist eine teilweise Bestellung. Aber es gibt keine Garantie, dass es schneller ist als der volle Argsort. – hpaulj

+0

@ B.M. Ja, sicher, ich muss das riesige Array n Mal durchlaufen, mit ungefähr. n * (len_array + 1 - n) greift auf array zu, wenn ich jedes Mal nach argmin suche und es dann aus dem Array ablege. – Daria

Antwort

0

Hier ist ein iterativer Ansatz, der schneller als argsort zu sein scheint, sofern n nicht zu groß ist:

In [135]: arr = np.arange(200000) 
In [136]: np.random.shuffle(arr) 
In [137]: def foo(arr): 
    ...:  arr=arr.copy() 
    ...:  alist=[] 
    ...:  for i in range(10): 
    ...:   k=np.argmin(arr) 
    ...:   alist.append(k) 
    ...:   arr[k]=200000 
    ...:  return alist 
    ...: 
In [138]: foo(arr) 
Out[138]: [176806, 180397, 139992, 151809, 59931, 59866, 130026, 191357, 84166, 130359] 
In [139]: np.argsort(arr)[:10] 
Out[139]: 
array([176806, 180397, 139992, 151809, 59931, 59866, 130026, 191357, 
     84166, 130359], dtype=int32) 
In [140]: timeit np.argsort(arr)[:10] 
100 loops, best of 3: 15.8 ms per loop 
In [141]: timeit foo(arr) 
1000 loops, best of 3: 1.69 ms per loop 

(Ich werde später kommentieren, wenn erforderlich).

+0

ok, ich habe versucht, einen Generator aus Ihrem Code zu bauen, und für die ersten paar Werte ist es okay. Vielen Dank! aber vielleicht ist es immer noch möglich, es besser zu machen? – Daria

+0

Es hängt stark von der relativen Geschwindigkeit von 'argmin' und' argsort' ab. Wenn Sie nur ein paar "Argmin" Schritte benötigen, ist diese Schleife deutlich besser. Aber für ein größeres 'n' ist es schneller, das Ganze ein für allemal zu sortieren. Und wie Panzer argumentiert, könnte das Sortieren in Blöcken mit 'argpartition' helfen - in ausgewählten Fällen. – hpaulj

Verwandte Themen