なぜnumpyはこの結果を出しているのですか?
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
私がそれを行うと期待するとき:
[3 2 0 1]
明らかに、機能についての私の理解が欠けています。
なぜnumpyはこの結果を出しているのですか?
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
私がそれを行うと期待するとき:
[3 2 0 1]
明らかに、機能についての私の理解が欠けています。
回答:
a = x.argsort()
、印刷x[a]
、取得しますarray([ 0. , 0.1 , 1.41, 1.48])
[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
により、等しい値の要素の処理方法をより詳細に制御できます。
argsort
ソートされた配列のインデックスを返します。ソートされたインデックスのインデックスはランクです。これは、2番目の呼び出しがargsort
返すものです。
ドキュメントは、言いますargsort
:
配列をソートするインデックスを返します。
つまり、argsortの最初の要素は、最初にソートされる要素のインデックスであり、2番目の要素は2番目にソートされる要素のインデックスです。
あなたが望んでいるように見えるのは、値のランク順です。これは、によって提供されるものですscipy.stats.rankdata
。ランクに同順位がある場合はどうなるかを考える必要があることに注意してください。
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
コードによる実際の実装に対して、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配列でのみ機能します。
[3 2 0 1]
正解だったと思いますか?