Transformiere eine Menge von Zahlen in numpy, so dass jede Zahl in eine Anzahl von anderen Zahlen umgewandelt wird, die kleiner sind

8

Betrachten Sie eine Reihe von Zahlen:

%Vor%

Nun möchte ich diese Menge in eine andere Menge y auf folgende Weise transformieren: für jedes Element i in x wäre das entsprechende Element j in y die Anzahl der anderen Elemente in x , die kleiner als i sind. Zum Beispiel würde das oben angegebene x wie folgt aussehen:

%Vor%

Jetzt kann ich das mit einfachen Python-Schleifen machen:

%Vor%

Wenn jedoch die Länge von x sehr groß ist, wird der Code extrem langsam. Ich habe mich gefragt, ob irgendeine nautische Magie zur Rettung gebracht werden kann. Wenn ich zum Beispiel alle Elemente kleiner als 0.5 filtern müsste, hätte ich einfach eine boolesche Maskierung verwendet:

%Vor%

Kann so etwas verwendet werden, damit dasselbe viel schneller erreicht werden kann?

    
Peaceful 20.12.2016, 12:15
quelle

4 Antworten

10

Was Sie eigentlich tun müssen, ist das inverse der Sortierreihenfolge Ihres Arrays:

%Vor%

Beispiel run (in ipython):

%Vor%

Alternativ, wenn Sie die Anzahl der Elemente größer als jedes entsprechende Element in x erhalten möchten, müssen Sie die Sortierung von aufsteigend zu absteigend umkehren. Eine mögliche Option ist, einfach die Konstruktion der Indizierung zu vertauschen:

%Vor%

ein anderer, wie @unutbu in einem Kommentar vorgeschlagen , wird das ursprüngliche Array dem neuen zugeordnet:

%Vor%     
Andras Deak 20.12.2016, 12:22
quelle
4

Hier ist ein Ansatz mit np.searchsorted -

%Vor%

Ein weiterer meist auf @Andras Deak's solution mit argsort() -

%Vor%

Beispiellauf -

%Vor%     
Divakar 20.12.2016 12:28
quelle
2

Zusätzlich zu den anderen Antworten könnte eine andere Lösung, die boolesche Indizierung verwendet, sein:

%Vor%

Für Ihr Beispiel:

%Vor%     
Michele 20.12.2016 12:45
quelle
2

Ich wollte zu diesem Beitrag beitragen, indem ich ein paar Tests mit @Andras Deaks Lösung versus argsort erneut vorstelle.

Es scheint, dass argsort für kurze Arrays wieder schneller ist. Eine einfache Idee ist es, zu bewerten, wie groß die Länge der Anordnung ist, in der wir die Balance verschieben.

Ich definiere drei Funktionen

  • construct ist die Lösung von Andras Deak
  • argsortagain was offensichtlich ist
  • attempted_optimal , die bei len(a) == 400 abschliesst

Funktionen

%Vor%

testen

%Vor%

Schlussfolgerung

attempted_optimal macht, was es tun soll. Aber ich bin mir nicht sicher, ob es sich für den marginalen Nutzen lohnt, der in einem Spektrum von Array-Länge (unter 400) gewonnen wird, wo es kaum darauf ankommt. Ich würde mich nur für constructed einsetzen.

Diese Analyse hat mir geholfen, zu dieser Schlussfolgerung zu kommen.

    
piRSquared 09.01.2017 21:34
quelle

Tags und Links