Numpy argsort-何をしていますか?


123

なぜnumpyはこの結果を出しているのですか?

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

>[2 3 1 0]

私がそれを行うと期待するとき:

[3 2 0 1]

明らかに、機能についての私の理解が欠けています。


6
なぜ[3 2 0 1]正解だったと思いますか?
zwol 2013

9
出力を逆に理解しました。つまり、xの最初の要素を取得する場合、それはソートされた配列の位置3にある必要があります。
user1276273 2013

26
あなたの考え方は完全に理にかなっています、私はまったく同じ質問を持っていました
adrienlucca.wordpress.com

2
[3 2 0 1]-これは値をランク付けしているため、実際のインデックスを取得していません。
Lahiru Karunaratne

ソートされた配列では、出力が元の配列での位置を示していることを思い出してください。つまり、output [0]は元の入力配列の最小要素が配置されるインデックスであり、最大要素のoutput [-1]です。
lincr

回答:


143

ドキュメントによると

配列をソートするインデックスを返します。

  • 2のインデックスです0.0
  • 3のインデックスです0.1
  • 1のインデックスです1.41
  • 0のインデックスです1.48

12
a = x.argsort()、印刷x[a]、取得しますarray([ 0. , 0.1 , 1.41, 1.48])
Belter 2017

39

[2, 3, 1, 0] 最小の要素がインデックス2にあり、次にインデックス3、次にインデックス1、次にインデックス0にあることを示します。

探している結果を得るには、いくつかの方法があります。

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

例えば、

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])

これにより、すべてが同じ結果を生成することが確認されます。

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))

これらのIPython %timeitベンチマークは、大規模な配列using_indexed_assignmentが最も高速であることを示唆しています。

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

小さな配列のusing_argsort_twice場合、より高速になる可能性があります:

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

また、これstats.rankdataにより、等しい値の要素の処理方法をより詳細に制御できます。


1
argsort()を2回適用するとランクが得られる理由について説明を追加できますか?
Phani 14

1
@Phani:argsortソートされた配列のインデックスを返します。ソートされたインデックスのインデックスはランクです。これは、2番目の呼び出しがargsort返すものです。
unutbu 14

2
最初のargsortは順列を返します(データに適用すると並べ替えられます)。argsortが(thisまたはany)順列に適用されると、逆順列が返されます(2つの順列がどちらかの順序で相互に適用された場合、結果はIdentityになります)。並べ替えられたデータ配列に適用された場合、2番目の順列は、並べ替えられていないデータ配列を生成します。つまり、それはランクです。
Alex C

1
吹き飛ばされた心。やっとわかった!元の配列のインデックスを内容とする配列を、並べ替えられた順序で返します。
ホセ・ア

3

ドキュメントは、言いますargsort

配列をソートするインデックスを返します。

つまり、argsortの最初の要素は、最初にソートされる要素のインデックスであり、2番目の要素は2番目にソートされる要素のインデックスです。

あなたが望んでいるように見えるのは、値のランク順です。これは、によって提供されるものですscipy.stats.rankdata。ランクに同順位がある場合はどうなるかを考える必要があることに注意してください。


3

numpy.argsort(a、axis = -1、kind = 'quicksort'、order = None)

配列をソートするインデックスを返します

kindキーワードで指定されたアルゴリズムを使用して、指定された軸に沿って間接ソートを実行します。ソートされた順序で、指定された軸に沿ってそのインデックスデータと同じ形状のインデックスの配列を返します。

次のように値のリストを持つPythonの例を考えてみましょう

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

次に、argsort関数を使用します。

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

出力は

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

これはlistExampleの値のインデックスのリストです。これらのインデックスをそれぞれの値にマッピングすると、次のような結果が得られます。

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

(この関数は多くの場所で非常に便利です。たとえば、リスト/配列をソートしたいが、list.sort()関数を使用したくない場合(つまり、リスト内の実際の値の順序を変更しない場合)、これを使用できます。関数。)

詳細については、次のリンクを参照してください。https//docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html


1

入力:
numpyをnpとしてインポート
x = np.array([1.48,1.41,0.0,0.1])
x.argsort()。argsort()

出力:
array([3、2、0、1])


1
このコードスニペットが解決策となる可能性がありますが、説明を含めると、投稿の品質を向上させるのに役立ちます。あなたは将来の読者のための質問に答えていることを覚えておいてください、そしてそれらの人々はあなたのコード提案の理由を知らないかもしれません。
平和タイプ


0

np.argsortは、「種類」(並べ替えアルゴリズムのタイプを指定)によって指定された並べ替えられた配列のインデックスを返します。ただし、np.argmaxでリストを使用すると、リスト内の最大の要素のインデックスが返されます。一方、np.sortは、指定された配列listをソートします。


0

コードによる実際の実装に対して、OPの当初の理解を直接対比したいだけです。

numpy.argsort 1D配列の場合、次のように定義されます。

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

OPは当初、1次元配列の場合は次のように定義されていると考えていました。

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

注:このコードは一般的なケースでは機能しません(1Dでのみ機能します)。この回答は、単に説明のためのものです。


x[x.argsort()]は必ずしもと同じではありませんnp.sort(x)。実際、同じ形である必要はありません。2D配列でこれを試してください。これは、1D配列でのみ機能します。
ネイサン

それは不必要に独断的だと感じています。問題は1D配列についてです。これは、使用するリテラルコードではなく、違いを理解する方法として意図されています。さらに、2D配列がある場合、どのような種類の並べ替えが必要かさえ明確ではありません。グローバルソートが必要ですか?そうでない場合、どの軸をソートする必要がありますか?とにかく、私は免責事項を追加しました。
Multihunter

0

与えられた配列インデックスに従ってインデックスを返します[1.48,1.41,0.0,0.1]。つまり 0.0、はインデックス[2]の最初の要素です。 0.1index [3]の2番目の要素です。 1.41インデックス[1]の3番目の要素です。 1.48index [0]の4番目の要素です。出力:

[2,3,1,0]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.