np.uniqueの結果をカウントで並びかえる

np.uniqueを使うと、配列の中の重複する要素を一つにしてくれる(関数名からもわかるぐらい単純な動作) これだけでも十分なんだけど、要素の数をキーにして並び変えたいと思うことがあるはず。

shellならば以下でできる。

$ cat $FILE | uniq -c | sort -n

numpyの場合はひと工夫が必要

まずはこんな感じの配列をユニークにするとしよう。

>>> X = np.random.randint(10, size=20)
>>> X
array([6, 5, 9, 8, 3, 3, 9, 8, 7, 0, 0, 7, 9, 8, 9, 6, 6, 1, 9, 7])

特に工夫なくnp.uniqueを実行するとこうなる。

>>> np.unique(X)
array([0, 1, 3, 5, 6, 7, 8, 9])

ユニークな配列はその要素の辞書順にソートされる。

ここでnp.uniquereturn_counts=Trueという引数を渡すと、それぞれの要素が元の配列にいくつあったのかを返してくれる。

>>> np.unique(X, return_counts=True)
(array([0, 1, 3, 5, 6, 7, 8, 9]), array([2, 1, 2, 1, 3, 3, 3, 5], dtype=int64))

これを利用してユニークな配列を要素のカウント数順に並び変える。 argsortでindexを指定するのがややトリッキーな感じはあるが、シンプルに目的を達していることがわかってもらえるかと思う。

>>> uniq, count = np.unique(X, return_counts=True)
>>> uniq[np.argsort(count)]
array([1, 5, 0, 3, 6, 7, 8, 9])