pandas.DataFrame, Seriesをソートするsort_values, sort_index

Modified: | Tags: Python, pandas

pandasでDataFrameSeriesをソート(並び替え)するには、sort_values()およびsort_index()メソッドを使う。昇順・降順を切り替えたり、複数列を基準にソートしたりできる。

なお、古いバージョンにあったsort()メソッドは廃止されているので注意。

昇順・降順に並べ替えるのではなく、昇順・降順に順位付けした結果を得るにはrank()、行名・列名を指定して任意の順番に並べ替えるにはreindex()を使う。

n個の最大値・最小値(大きい方からn個、小さい方からn個)を含む行・要素を取り出すnlargest(), nsmallest()もある。

本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。例として以下のデータを使用する。

import pandas as pd

print(pd.__version__)
# 2.1.4

df = pd.read_csv('data/src/sample_pandas_normal.csv')
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

例はDataFrameだが、Seriesでもsort_values()sort_index()が用意されている。使い方は同じ。

要素でソートするsort_values()

要素の値に応じてソートするにはsort_values()メソッドを使う。

基準列を指定: 引数by

ソートしたい列のラベル(列名)を第一引数byに指定する。

print(df.sort_values('age'))
#       name  age state  point
# 2  Charlie   18    CA     70
# 0    Alice   24    NY     64
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57
# 1      Bob   42    CA     92
# 3     Dave   68    TX     70

print(df.sort_values('state'))
#       name  age state  point
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88
# 0    Alice   24    NY     64
# 5    Frank   30    NY     57
# 3     Dave   68    TX     70

複数列を基準にソート

第一引数byをリストで指定すると、複数列を基準にソートできる。

リストの後ろに指定した列から順番にソートされ、最終的にはリストの先頭に指定した列でソートされる。

print(df.sort_values(['age', 'state']))
#       name  age state  point
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88
# 0    Alice   24    NY     64
# 5    Frank   30    NY     57
# 1      Bob   42    CA     92
# 3     Dave   68    TX     70

print(df.sort_values(['state', 'age']))
#       name  age state  point
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88
# 1      Bob   42    CA     92
# 0    Alice   24    NY     64
# 5    Frank   30    NY     57
# 3     Dave   68    TX     70

昇順・降順の指定: 引数ascending

デフォルトは昇順。降順にするには引数ascendingFalseにする。

print(df.sort_values('age', ascending=False))
#       name  age state  point
# 3     Dave   68    TX     70
# 1      Bob   42    CA     92
# 5    Frank   30    NY     57
# 0    Alice   24    NY     64
# 4    Ellen   24    CA     88
# 2  Charlie   18    CA     70

複数列を基準にソートする場合、引数ascendingをリストで指定すると、それぞれの列に対して昇順・降順を選択できる。

print(df.sort_values(['age', 'state'], ascending=False))
#       name  age state  point
# 3     Dave   68    TX     70
# 1      Bob   42    CA     92
# 5    Frank   30    NY     57
# 0    Alice   24    NY     64
# 4    Ellen   24    CA     88
# 2  Charlie   18    CA     70

print(df.sort_values(['age', 'state'], ascending=[True, False]))
#       name  age state  point
# 2  Charlie   18    CA     70
# 0    Alice   24    NY     64
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57
# 1      Bob   42    CA     92
# 3     Dave   68    TX     70

インデックスを振り直し: 引数ignore_index

デフォルトではインデックス(行名)も合わせて並べ替えられる。引数ignore_indexTrueとすると、0始まりの連番に振り直される。

print(df.sort_values('age', ignore_index=True))
#       name  age state  point
# 0  Charlie   18    CA     70
# 1    Alice   24    NY     64
# 2    Ellen   24    CA     88
# 3    Frank   30    NY     57
# 4      Bob   42    CA     92
# 5     Dave   68    TX     70

欠損値NaNの扱い: 引数na_position

欠損値NaNがある場合、デフォルトでは末尾に並べられる。

df_nan = df.copy()
df_nan.iloc[0, 1] = float('nan')
df_nan.iloc[4, 1] = float('nan')
print(df_nan)
#       name   age state  point
# 0    Alice   NaN    NY     64
# 1      Bob  42.0    CA     92
# 2  Charlie  18.0    CA     70
# 3     Dave  68.0    TX     70
# 4    Ellen   NaN    CA     88
# 5    Frank  30.0    NY     57

print(df_nan.sort_values('age'))
#       name   age state  point
# 2  Charlie  18.0    CA     70
# 5    Frank  30.0    NY     57
# 1      Bob  42.0    CA     92
# 3     Dave  68.0    TX     70
# 0    Alice   NaN    NY     64
# 4    Ellen   NaN    CA     88

引数na_position'first'とすると先頭に並べられる。

print(df_nan.sort_values('age', na_position='first'))
#       name   age state  point
# 0    Alice   NaN    NY     64
# 4    Ellen   NaN    CA     88
# 2  Charlie  18.0    CA     70
# 5    Frank  30.0    NY     57
# 1      Bob  42.0    CA     92
# 3     Dave  68.0    TX     70

欠損値を削除したり別の値に置換したりする方法については以下の記事を参照。

関数を適用した結果を元にソート: 引数key

Pythonの組み込み関数sorted()などのように、sort_values()でも引数keyを指定できる。引数keyに指定した関数がソートされる前に適用され、その結果を元にソートされる。

文字列の長さ(文字数)でソートする例は以下の通り。ラムダ式でSeriesの文字列メソッドを適用している。

print(df.sort_values('name', key=lambda s: s.str.len()))
#       name  age state  point
# 1      Bob   42    CA     92
# 3     Dave   68    TX     70
# 0    Alice   24    NY     64
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57
# 2  Charlie   18    CA     70

sort_values()の引数keyには、Seriesを受け取りSeriesやリストなどのarray-likeオブジェクトを返す関数を指定する必要があるので注意。

各要素に任意の関数を適用するにはmap()メソッドを使う。以下の例では説明のためにSeriesの文字列メソッドを使わず、map()で組み込み関数len()を適用している。

# print(df.sort_values('name', key=len))
# TypeError: object of type 'int' has no len()

print(df.sort_values('name', key=lambda s: s.map(len)))
#       name  age state  point
# 1      Bob   42    CA     92
# 3     Dave   68    TX     70
# 0    Alice   24    NY     64
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57
# 2  Charlie   18    CA     70

引数keyを利用すると任意のルールに従って並べ替えられる。都道府県名を都道府県コード順にソートする例は以下の記事を参照。

ソートアルゴリズムを指定: 引数kind

引数kindにソートアルゴリズムを指定できる。'quicksort'(デフォルト), 'mergesort', 'heapsort', 'stable'を指定可能。各アルゴリズムの詳細は以下のNumPy公式ドキュメントを参照。

複数列を基準にソートする場合はこの引数の指定は無視される。

行を基準に列をソート: 引数axis

これまでの例のように、デフォルトでは列を基準に行がソートされる。行を基準に列をソートするには引数axis1または'columns'とする。

数値と文字列が混在しているとエラーになるので、ここではselect_dtypes()で数値の列のみを抽出している。

df_num = df.select_dtypes('number')
print(df_num)
#    age  point
# 0   24     64
# 1   42     92
# 2   18     70
# 3   68     70
# 4   24     88
# 5   30     57

print(df_num.sort_values(1, axis=1, ascending=False))
#    point  age
# 0     64   24
# 1     92   42
# 2     70   18
# 3     70   68
# 4     88   24
# 5     57   30

元のオブジェクトを変更: 引数inplace

デフォルトではソートされた新たなオブジェクトが返されるが、引数inplaceTrueとすると、元のオブジェクト自体が変更される。

df_copy = df.copy()
df_copy.sort_values('age', inplace=True)
print(df_copy)
#       name  age state  point
# 2  Charlie   18    CA     70
# 0    Alice   24    NY     64
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57
# 1      Bob   42    CA     92
# 3     Dave   68    TX     70

インデックス(行名・列名)でソートするsort_index()

インデックス(行名・列名)でソートするにはsort_index()メソッドを使う。

行名indexでソート

デフォルトでは行名indexに従って行がソートされる。

df_sorted = df.sort_values('age')
print(df_sorted)
#       name  age state  point
# 2  Charlie   18    CA     70
# 0    Alice   24    NY     64
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57
# 1      Bob   42    CA     92
# 3     Dave   68    TX     70

print(df_sorted.sort_index())
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

列名columnsでソート: 引数axis

引数axis1または'columns'とすると、列名columnsに従って列がソートされる。

print(df.sort_index(axis=1))
#    age     name  point state
# 0   24    Alice     64    NY
# 1   42      Bob     92    CA
# 2   18  Charlie     70    CA
# 3   68     Dave     70    TX
# 4   24    Ellen     88    CA
# 5   30    Frank     57    NY

sort_values()と同じ引数を指定可能

sort_index()でも引数ascending, ignore_index, na_position, key, kind, inplaceを指定可能。行名indexや列名columnsが対象になるだけで、使い方はsort_values()と同じ。

print(df.sort_index(axis=1, ascending=False, key=lambda s: s.str.len()))
#   state  point     name  age
# 0    NY     64    Alice   24
# 1    CA     92      Bob   42
# 2    CA     70  Charlie   18
# 3    TX     70     Dave   68
# 4    CA     88    Ellen   24
# 5    NY     57    Frank   30

関連カテゴリー

関連記事