Remrinのpython攻略日記

python3に入門しました。python3についてあれこれとサンプルコードとか。

NumPyの使い方(9) 並べ替えsortなど

NumPyのsortについて。
 

sort()メソッド 内部で配列をソート。返り値はNone
np.sort()関数 ソート済み配列を返す。元の配列は保存。

 

# coding: utf-8
import numpy as np

np.random.seed(1)
a1 = np.random.randint(0, 100, 10)
print(a1)  # [37 12 72  9 75  5 79 64 16  1]

a1.sort()
print(a1)        # [ 1  5  9 12 16 37 64 72 75 79]

print(a1.sort()) # None

np.random.seed(1)
a1 = np.random.randint(0, 100, 10)
print(a1)  # [37 12 72  9 75  5 79 64 16  1]

a2 = np.sort(a1)
print(a1)  # [37 12 72  9 75  5 79 64 16  1] 元配列は保存
print(a2)  # [ 1  5  9 12 16 37 64 72 75 79]

 

axisオプション

 どのaxisでソートするかのオプション
 列内でのソートはaxis=0とするか、あるいは単に0
 行内でのソートはaxis=1とするか、あるいは単に1
 デフォルトは-1で、最後の軸(2次元ならaxis=1)でソート
 axisをNoneとすると1次元配列に平坦化。

np.random.seed(1)
a3 = np.random.randint(0, 100, (3, 6))
print(a3)
# [[37 12 72  9 75  5]
#  [79 64 16  1 76 71]
#  [ 6 25 50 20 18 84]]

# axis=0
print(np.sort(a3, 0))
# [[ 6 12 16  1 18  5]
#  [37 25 50  9 75 71]
#  [79 64 72 20 76 84]]

# axis=1
print(np.sort(a3, 1))
# [[ 5  9 12 37 72 75]
#  [ 1 16 64 71 76 79]
#  [ 6 18 20 25 50 84]]

# axis=-1
print(np.sort(a3, axis=-1))
# [[ 5  9 12 37 72 75]
#  [ 1 16 64 71 76 79]
#  [ 6 18 20 25 50 84]]

# axisのデフォルトは-1
print(np.sort(a3))
# [[ 5  9 12 37 72 75]
#  [ 1 16 64 71 76 79]
#  [ 6 18 20 25 50 84]]

# axis=None
print(np.sort(a3, axis=None))
# [ 1  5  6 ..., 76 79 84]

 

kindオプション

 ソートに利用するアルゴリズムを選ぶ。デフォルトは'quicksort'

kind speed worst case stable
'quicksort' 1 O(n^2) ×
'mergesort' 2 O(n*log(n)
'heapsort' 3 O(n*log(n) ×

stable:等しい要素の並び順を保存
 

orderオプション

フィールドをもつ要素のばあい、キーとするフィールドを指定できる。

dtype = [("name", 'U10'), ("height", int), ("age", int)]
values = [("香川", 165, 48), ("秋山", 175, 32), ("長田", 170, 27)]
a1 = np.array(values, dtype=dtype)
print(a1)
# [('香川', 165, 48) ('秋山', 175, 32) ('長田', 170, 27)]

print(a1.dtype)
# [('name', '<U10'), ('height', '<i4'), ('age', '<i4')]

print(np.sort(a1, order="age"))
# [('長田', 170, 27) ('秋山', 175, 32) ('香川', 165, 48)]

 

逆順ソート

降順配列にするには

array[::-1]    行を逆順にする
array[:, ::-1] 列を逆順にする

などのスライスを使う。
 

np.random.seed(1)
a3 = np.random.randint(0, 100, (3, 6))
print(a3)
# [[37 12 72  9 75  5]
#  [79 64 16  1 76 71]
#  [ 6 25 50 20 18 84]]

# axis=0の逆順ソート
print(np.sort(a3, 0)[::-1])
# [[79 64 72 20 76 84]
#  [37 25 50  9 75 71]
#  [ 6 12 16  1 18  5]]

# axis=1の逆順ソート
print(np.sort(a3, 1)[:, ::-1])
# [[75 72 37 12  9  5]
#  [79 76 71 64 16  1]
#  [84 50 25 20 18  6]]

argsort()

argsort()はソートした場合のindex番号の配列を取得する。

1次元配列の場合

a1 = np.array([37, 12, 72, 9, 75, 5])

# argsort()...ソートした場合のindex番号を配列にする
indexer = a1.argsort()
print(indexer)
# [5 3 1 0 2 4]   a1[5] < a1[3] < a1[1] < a1[0] ...

print(a1[indexer])
# [ 5  9 12 37 72 75]

 
2次元配列の場合は、argsort()でキーとする行の指定ができる。

np.random.seed(1)
a1 = np.random.randint(0, 100, (3, 6))
print(a1)
# [[37 12 72  9 75  5]
#  [79 64 16  1 76 71]
#  [ 6 25 50 20 18 84]]

#0行目をキーとしてソート
print(a1[:, a1[0].argsort()])
# [[ 5  9 12 37 72 75]
#  [71  1 64 79 16 76]
#  [84 20 25  6 50 18]]

#1行目をキーとしてソート
print(a1[:, a1[1].argsort()])
# [[ 9 72 12  5 75 37]
#  [ 1 16 64 71 76 79]
#  [20 50 25 84 18  6]]

 
argsortにもaxis, kind, orderオプションがある。
 

lexsort()

複数のキーで間接ソートするときに使う。
lexsort()もargsort()同様にインデックスの配列を得る。

last_name = ["はつね", "さとう", "しまだ", "さとう"]
first_name = ["みく", "めぐみ","なおみ", "かな"] 

indexer = np.lexsort((first_name, last_name))
print(indexer) # [3 1 2 0 ]

name =[(last_name[i], first_name[i]) for i in indexer]
print(name)
# [('さとう', 'かな'), ('さとう', 'めぐみ'), ('しまだ', 'なおみ'), ('はつね', 'みく')]

 

searchsorted()

ソートされた配列内で二分探索をし、挿入される位置を返す。

a1 = np.array([0, 5, 10, 15, 20])
print(a1.searchsorted(7))          # 2
print(a1.searchsorted(18))         # 4
print(a1.searchsorted(5))          # 1

print(a1.searchsorted([7, 18, 5])) # [2 4 1]

 
sideオプション:同じ値が複数あるとき、
'left' もっとも左のインデックス。(デフォルト)
'right' もっとも右のインデックス

a1 = np.array([1, 1, 1, 2, 2, 2])
print(a1.searchsorted([1, 2]))                # [0 3]
print(a1.searchsorted([1, 2], side="right"))  # [3 6]

 

np.unique()

1次元の配列から重複を取り除き、ソートした配列を返す。
python標準のsorted(set(seq))と同様の働き。

a1 = np.array([1, 3, 2, 0, 1, 2, 2, 1])
print(np.unique(a1))  # [0 1 2 3]

 
return_index=Trueとすると初回のインデックスを返す。
return_counts=Trueとすると、重複している回数を返す。

print(np.unique(a1, return_index=True))
# (array([0, 1, 2, 3]), array([3, 0, 2, 1], dtype=int32))

print(np.unique(a1, return_counts=True))
# (array([0, 1, 2, 3]), array([1, 3, 3, 1]))