NumPyのsortとargsort関数で任意の行・列を基準にソート
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.DataFrame
とnumpy.ndarray
は相互に変換できる。
- 関連記事: pandas.DataFrame, Seriesをソートするsort_values, sort_index
- 関連記事: pandas.DataFrame, SeriesとNumPy配列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]]