NumPyのsortとargsort関数で任意の行・列を基準にソート

Modified: | Tags: Python, NumPy

NumPyの関数numpy.sort()を2次元のNumPy配列ndarrayに適用すると、各行・各列の値が別々に昇順にソートされたndarrayを取得できる。

特定の行または列を基準にソートしたい場合はnumpy.argsort()を使う。numpy.argsort()はソートされた値ではなくインデックスのndarrayを返す関数。

ここでは、

  • numpy.sort()の使い方: 並べ替えた配列ndarrayを取得
  • ndarray.sort()の使い方: 配列ndarray自身を並べ替える
  • numpy.argsort()の使い方: 並べ替えたインデックスの配列ndarrayを取得
  • 特定の行または列を基準にソートする方法

について、サンプルコードとともに説明する。

昇順・降順ではなく任意の順番に並べ替えたい場合は以下の記事を参照。

numpy.sort()の使い方: 並べ替えた配列ndarrayを取得

一次元配列の場合

第一引数に元となる配列ndarrayを指定する。

一次元配列の場合は単純に昇順にソートされる。

ソートされた新たなndarrayが返され、元のndarrayはそのまま。

import numpy as np

a = np.array([3, 4, 2, 0, 1])
print(a)
# [3 4 2 0 1]

a_sort = np.sort(a)
print(a_sort)
# [0 1 2 3 4]

print(a)
# [3 4 2 0 1]

ndarrayのメソッドsort()を使うとndarray自身が更新される。後述。

np.sort()関数にはPython標準のsort()メソッドやsorted()関数のように引数reverseは存在しない。降順にしたい場合はスライス[::-1]を使う。

a_sort_reverse = np.sort(a)[::-1]
print(a_sort_reverse)
# [4 3 2 1 0]

多次元配列の場合

二次元配列を例とする。

a_2d = np.array([[20, 3, 100], [1, 200, 30], [300, 10, 2]])
print(a_2d)
# [[ 20   3 100]
#  [  1 200  30]
#  [300  10   2]]

引数axisでソートする軸を選択する。

二次元配列の場合はaxis=0で列に対してソート、axis=1で行に対してソートされる。各列・各行の値が別々に並べ替えられる。

a_2d_sort_col = np.sort(a_2d, axis=0)
print(a_2d_sort_col)
# [[  1   3   2]
#  [ 20  10  30]
#  [300 200 100]]

a_2d_sort_row = np.sort(a_2d, axis=1)
print(a_2d_sort_row)
# [[  3  20 100]
#  [  1  30 200]
#  [  2  10 300]]

デフォルトはaxis=-1で最後の軸に沿ってソートされる。二次元配列の場合は行に対してソートされる。

a_2d_sort_row = np.sort(a_2d)
print(a_2d_sort_row)
# [[  3  20 100]
#  [  1  30 200]
#  [  2  10 300]]

a_2d_sort_row = np.sort(a_2d, axis=-1)
print(a_2d_sort_row)
# [[  3  20 100]
#  [  1  30 200]
#  [  2  10 300]]

降順にしたい場合は、各軸に対してスライス[::-1]を使う。末尾の, ;は省略可能([::-1][::-1, :]と等価)。

a_2d_sort_col_reverse = np.sort(a_2d, axis=0)[::-1]
print(a_2d_sort_col_reverse)
# [[300 200 100]
#  [ 20  10  30]
#  [  1   3   2]]

a_2d_sort_row_reverse = np.sort(a_2d, axis=1)[:, ::-1]
print(a_2d_sort_row_reverse)
# [[100  20   3]
#  [200  30   1]
#  [300  10   2]]

ndarray.sort()の使い方: 配列ndarray自身を並べ替える

関数ではなく、NumPy配列ndarrayのメソッドとしてsort()が用意されている。

ndarray自身が並べ替えられ更新される。引数は関数numpy.sort()と同じ。

print(a_2d)
# [[ 20   3 100]
#  [  1 200  30]
#  [300  10   2]]

a_2d.sort()

print(a_2d)
# [[  3  20 100]
#  [  1  30 200]
#  [  2  10 300]]

a_2d.sort(axis=0)

print(a_2d[::-1])
# [[  3  30 300]
#  [  2  20 200]
#  [  1  10 100]]

numpy.argsort()の使い方: 並べ替えたインデックスの配列ndarrayを取得

np.argsort()は値ではなく並び替えたインデックス(元のndarrayでの位置 = 0始まりの順番)のndarrayを返す。引数axisなどの考え方はnp.sort()と同じ。

a_2d = np.array([[20, 3, 100], [1, 200, 30], [300, 10, 2]])
print(a_2d)
# [[ 20   3 100]
#  [  1 200  30]
#  [300  10   2]]

a_2d_sort_col_index = np.argsort(a_2d, axis=0)
print(a_2d_sort_col_index)
# [[1 0 2]
#  [0 2 1]
#  [2 1 0]]

a_2d_sort_row_index = np.argsort(a_2d)
print(a_2d_sort_row_index)
# [[1 0 2]
#  [0 2 1]
#  [2 1 0]]

特定の行または列を基準にソートする方法

多次元配列を、np.sort()のように各行や各列をそれぞれソートするのではなく、任意の行または列を基準にソートする場合は、np.argsort()を使う。

np.argsort()で基準となる行または列のインデックスを取得し、それに従って行・列を並べ替えるという流れ。ndarrayの行・列を任意の順番に並べ替える方法についての詳細は以下の記事を参照。

なお、この方法は複雑なので、pandasのsort_values()を使うほうが簡単でオススメ。pandas.DataFramenumpy.ndarrayは相互に変換できる。

特定の列を基準にソート

np.argsort()で基準となる行または列のインデックスを取得。

print(a_2d)
# [[ 20   3 100]
#  [  1 200  30]
#  [300  10   2]]

col_num = 1

print(a_2d[:, col_num])
# [  3 200  10]

print(np.argsort(a_2d[:, col_num]))
# [0 2 1]

そのインデックスをもとに行を並べ替える。

a_2d_sort_col_num = a_2d[np.argsort(a_2d[:, col_num])]
print(a_2d_sort_col_num)
# [[ 20   3 100]
#  [300  10   2]
#  [  1 200  30]]

降順にしたい場合、np.argsort()で取得するインデックスを[::-1]で逆順にする。

print(np.argsort(a_2d[:, col_num])[::-1])
# [1 2 0]

a_2d_sort_col_num_reverse = a_2d[np.argsort(a_2d[:, col_num])[::-1]]
print(a_2d_sort_col_num_reverse)
# [[  1 200  30]
#  [300  10   2]
#  [ 20   3 100]]

特定の行を基準にソート

行の場合も列の場合と同様。

row_num = 1

print(a_2d[row_num])
# [  1 200  30]

print(np.argsort(a_2d[row_num]))
# [0 2 1]

a_2d_sort_row_num = a_2d[:, np.argsort(a_2d[row_num])]
print(a_2d_sort_row_num)
# [[ 20 100   3]
#  [  1  30 200]
#  [300   2  10]]

print(np.argsort(a_2d[row_num])[::-1])
# [1 2 0]

a_2d_sort_row_num_inverse = a_2d[:, np.argsort(a_2d[row_num])[::-1]]
print(a_2d_sort_row_num_inverse)
# [[  3 100  20]
#  [200  30   1]
#  [ 10   2 300]]

関連カテゴリー

関連記事