読者です 読者をやめる 読者になる 読者になる

pandasで値の順位を取得したい(おまけにソート方法いろいろ)

pandasでDataFrameにorderを付与したいときのメモ

状況

↓こういうDataFrameに対して、testカラムの値が並び替えた時に何番目になるのかを知りたい

   test
0     1
1     4
2     6
3     3
4     2
5     7
6     9

具体的には、こういう結果がほしい

   test  order
0     1      0
1     4      3
2     6      4
3     3      2
4     2      1
5     7      5
6     9      6

値で並び替える方法はたくさんあるし、並び替えた時に何番目にすればいいのかのindexを取得してくる方法もたくさんあるが、 並び替えた時に何番目になるのかを取得してくる方法が意外となかった。(みんな考えるまでもないのだろうか?)

解決方法

追記

以前の方法(↓に書いてある方法)では同値を適切に扱えてなかった。 scipyを使うとめちゃくちゃカンタンにできた。 stats.mstats.rankdataという関数がそれ。

from scipy import stats
test = np.array([1,4,6,3,2,7,6])
a=pd.DataFrame(test, columns=(['test']))
a = a.assign(order=stats.mstats.rankdata(a.test))

で実現できる

以下のような出力が得られる。同値は小数で表示される。 (この例の場合、indexが2と6のところで5位タイが存在するが、5.5位として表示される)

   test  order
0     1    1.0
1     4    4.0
2     6    5.5
3     3    3.0
4     2    2.0
5     7    7.0
6     6    5.5

以下追記前の方法

(雑だが)aというDataFrameのtestカラムで並び替えた時の順位が知りたい場合、

np.argsort(a.sort_values('test').index)

で取得できる。

全体はこんな感じ

test = np.array([1,4,6,3,2,7,9])
a=pd.DataFrame(test, columns=(['test']))
a = a.assign(order=np.argsort(a.sort_values('test').index))

上のような結果が得られる。

おまけ

単純に並び替える

>>> a.sort_values('test')
   test
0     1
4     2
3     3
1     4
2     6
5     7
6     9

並び替えた時のインデックスを取得

たまにインデックスだけほしくなる。

>>> a.sort_values('test').index.values
array([0, 4, 3, 1, 2, 5, 6])

こうすれば並び替えることができる。

>>> [a.get_value(i, 'test') for i in a.sort_values('test').index]
[1, 2, 3, 4, 6, 7, 9]

こういう用途であればそもそもこれで完結するが、

>>> a.sort_values('test').test.values
array([1, 2, 3, 4, 6, 7, 9])

以上、メモでした。