Numpy Argsort - was macht es?


123

Warum gibt numpy dieses Ergebnis:

x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()

>[2 3 1 0]

wenn ich das erwarten würde:

[3 2 0 1]

Offensichtlich fehlt mein Verständnis der Funktion.


6
Warum denkst du, [3 2 0 1]wäre die richtige Antwort gewesen?
zwol

9
Ich hatte gerade ein umgekehrtes Verständnis der Ausgabe. Das heißt, wenn Sie das erste Element von x nehmen, sollte es sich an Position 3 eines sortierten Arrays befinden und so weiter.
user1276273

26
Ihre Denkweise ist völlig sinnvoll, ich hatte genau die gleiche Frage
adrienlucca.wordpress.com

2
[3 2 0 1] - Dies ist eine Rangfolge der Werte. Sie erhalten nicht die tatsächlichen Indizes.
Lahiru Karunaratne

Nur um sich daran zu erinnern, dass die Ausgabe Positionen im ursprünglichen Array anzeigt, während Sie es im sortierten Array denken. Das heißt, Ausgabe [0] ist der Index, in dem das kleinste Element im ursprünglichen Eingabearray gefunden und [-1] für das größte Element ausgegeben wird.
27.

Antworten:


143

Laut Dokumentation

Gibt die Indizes zurück, die ein Array sortieren würden.

  • 2ist der Index von 0.0.
  • 3ist der Index von 0.1.
  • 1ist der Index von 1.41.
  • 0ist der Index von 1.48.

12
a = x.argsort(), drucken x[a], wir werden bekommenarray([ 0. , 0.1 , 1.41, 1.48])
Belter

39

[2, 3, 1, 0] gibt an, dass sich das kleinste Element bei Index 2 befindet, das nächstkleinere bei Index 3, dann Index 1 und dann Index 0.

Es gibt verschiedene Möglichkeiten , um das gewünschte Ergebnis zu erzielen:

import numpy as np
import scipy.stats as stats

def using_indexed_assignment(x):
    "https://stackoverflow.com/a/5284703/190597 (Sven Marnach)"
    result = np.empty(len(x), dtype=int)
    temp = x.argsort()
    result[temp] = np.arange(len(x))
    return result

def using_rankdata(x):
    return stats.rankdata(x)-1

def using_argsort_twice(x):
    "https://stackoverflow.com/a/6266510/190597 (k.rooijers)"
    return np.argsort(np.argsort(x))

def using_digitize(x):
    unique_vals, index = np.unique(x, return_inverse=True)
    return np.digitize(x, bins=unique_vals) - 1

Beispielsweise,

In [72]: x = np.array([1.48,1.41,0.0,0.1])

In [73]: using_indexed_assignment(x)
Out[73]: array([3, 2, 0, 1])

Dadurch wird überprüft, ob alle das gleiche Ergebnis erzielen:

x = np.random.random(10**5)
expected = using_indexed_assignment(x)
for func in (using_argsort_twice, using_digitize, using_rankdata):
    assert np.allclose(expected, func(x))

Diese IPython- %timeitBenchmarks legen nahe, dass große Arrays using_indexed_assignmentam schnellsten sind:

In [50]: x = np.random.random(10**5)
In [66]: %timeit using_indexed_assignment(x)
100 loops, best of 3: 9.32 ms per loop

In [70]: %timeit using_rankdata(x)
100 loops, best of 3: 10.6 ms per loop

In [56]: %timeit using_argsort_twice(x)
100 loops, best of 3: 16.2 ms per loop

In [59]: %timeit using_digitize(x)
10 loops, best of 3: 27 ms per loop

Bei kleinen Arrays using_argsort_twicekann dies schneller sein:

In [78]: x = np.random.random(10**2)

In [81]: %timeit using_argsort_twice(x)
100000 loops, best of 3: 3.45 µs per loop

In [79]: %timeit using_indexed_assignment(x)
100000 loops, best of 3: 4.78 µs per loop

In [80]: %timeit using_rankdata(x)
100000 loops, best of 3: 19 µs per loop

In [82]: %timeit using_digitize(x)
10000 loops, best of 3: 26.2 µs per loop

Beachten Sie auch, dass stats.rankdataSie mehr Kontrolle darüber haben, wie Sie mit gleichwertigen Elementen umgehen.


1
Können Sie eine Erklärung hinzufügen, warum die zweimalige Anwendung von argsort () uns den Rang verleiht?
Phani

1
@Phani: Gibt argsortdie Indizes des sortierten Arrays zurück. Der Index der sortierten Indizes ist der Rang. Dies ist, was der zweite Aufruf argsortzurückgibt.
Unutbu

2
Der erste Argsort gibt eine Permutation zurück (die bei Anwendung auf die Daten sortiert würde). Wenn argsort auf (diese oder eine beliebige) Permutation angewendet wird, wird die inverse Permutation zurückgegeben (wenn die beiden Permutationen in einer beliebigen Reihenfolge aufeinander angewendet werden, ist das Ergebnis die Identität). Die zweite Permutation, wenn sie auf ein sortiertes Datenarray angewendet wird, würde das unsortierte Datenarray erzeugen, dh es ist der Rang.
Alex C

1
Verblüfft. Ich habe es endlich verstanden! Es gibt ein Array zurück, dessen Inhalt die Indizes des ursprünglichen Arrays in einer sortierten Reihenfolge sind.
Jose A

3

Wie die Dokumentation sagt argsort:

Gibt die Indizes zurück, die ein Array sortieren würden.

Das heißt, das erste Element der Argsortierung ist der Index des Elements, das zuerst sortiert werden soll, das zweite Element ist der Index des Elements, das an zweiter Stelle stehen soll usw.

Was Sie zu wollen scheinen, ist die Rangfolge der Werte, die von bereitgestellt wird scipy.stats.rankdata. Beachten Sie, dass Sie darüber nachdenken müssen, was passieren soll, wenn es Bindungen in den Reihen gibt.


3

numpy.argsort (a, Achse = -1, Art = 'Quicksort', Reihenfolge = Keine)

Gibt die Indizes zurück, die ein Array sortieren würden

Führen Sie eine indirekte Sortierung entlang der angegebenen Achse mit dem durch das Schlüsselwort kind angegebenen Algorithmus durch. Es gibt ein Array von Indizes mit derselben Form wie diese Indexdaten entlang der angegebenen Achse in sortierter Reihenfolge zurück.

Betrachten Sie ein Beispiel in Python mit einer Liste von Werten als

listExample  = [0 , 2, 2456,  2000, 5000, 0, 1]

Jetzt verwenden wir die Argsort-Funktion:

import numpy as np
list(np.argsort(listExample))

Die Ausgabe wird sein

[0, 5, 6, 1, 3, 2, 4]

Dies ist die Liste der Werteindizes in listBeispiel Wenn Sie diese Indizes den jeweiligen Werten zuordnen, erhalten wir das Ergebnis wie folgt:

[0, 0, 1, 2, 2000, 2456, 5000]

(Ich finde diese Funktion an vielen Stellen sehr nützlich, z. B. Wenn Sie die Liste / das Array sortieren möchten, aber die Funktion list.sort () nicht verwenden möchten (dh ohne die Reihenfolge der tatsächlichen Werte in der Liste zu ändern), können Sie diese verwenden Funktion.)

Weitere Informationen finden Sie unter folgendem Link: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html


1

Eingabe:
importiere numpy als np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort ()

Ausgabe:
Array ([3, 2, 0, 1])


1
Während dieses Code-Snippet die Lösung sein kann, hilft das Hinzufügen einer Erklärung wirklich, die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage in Zukunft für Leser beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen.
Friedenstyp

0

Zuerst wurde das Array bestellt. Generieren Sie dann ein Array mit dem Anfangsindex des Arrays.


0

np.argsort gibt den Index des sortierten Arrays zurück, der durch die 'Art' angegeben wird (die den Typ des Sortieralgorithmus angibt). Wenn jedoch eine Liste mit np.argmax verwendet wird, wird der Index des größten Elements in der Liste zurückgegeben. Während np.sort das angegebene Array sortiert, listet es auf.


0

Ich möchte nur das ursprüngliche Verständnis des OP direkt mit der tatsächlichen Implementierung mit Code vergleichen.

numpy.argsort ist so definiert, dass für 1D-Arrays:

x[x.argsort()] == numpy.sort(x) # this will be an array of True's

Das OP dachte ursprünglich, dass es so definiert wurde, dass für 1D-Arrays:

x == numpy.sort(x)[x.argsort()] # this will not be True

Hinweis: Dieser Code funktioniert im allgemeinen Fall nicht (funktioniert nur für 1D). Diese Antwort dient nur zur Veranschaulichung.


x[x.argsort()]ist nicht unbedingt das gleiche wie np.sort(x). In der Tat ist es nicht unbedingt die gleiche Form. Versuchen Sie dies mit einem 2D-Array. Dies funktioniert nur mit 1D-Arrays.
Nathan

Ich finde das unnötig pedantisch. Die Frage betrifft 1D-Arrays. Dies ist dazu gedacht, den Unterschied zu verstehen, anstatt wörtlichen Code zu verwenden. Wenn Sie ein 2D-Array haben, ist nicht einmal klar, welche Art von Sortierung Sie wünschen. Möchten Sie eine globale Sortierung? Wenn nicht, welche Achse soll sortiert werden? Unabhängig davon habe ich einen Haftungsausschluss hinzugefügt.
Multihunter

0

Es gibt Indizes gemäß den angegebenen Array-Indizes zurück, [1.48,1.41,0.0,0.1]dh: 0.0ist das erste Element in Index [2]. 0.1ist das zweite Element in Index [3]. 1.41ist das dritte Element in Index [1]. 1.48ist das vierte Element im Index [0]. Ausgabe:

[2,3,1,0]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.