pandas
のDataFrame
, Sereis
では、データやインデックスをもとに並べ替え(ソート)が行えます。
しかし、実際にソートしようとすると、次のような問題に直面することも…
- データのソートには、どのメソッドを使うの?
- 昇順、降順の設定方法、
- 複数列で並べ替えはどうするの?
このような疑問を解決するため、この記事ではDataFrame
の並べ替えを詳しく解説していきます。
pandasの並べ替えの基本
pandas
で、データの並べ替えをする際は、次のメソッドを使用します。
- インデックスで並べ替え|
.sort_index()
- データ列で並べ替え|
.sort_values()
インデックスをもとに並べ替えるか、データ列で並べ替えるかで、使用するメソッドが異なる点に注意しましょう。
次のサンプルデータを使用して、基本挙動を確認してみます。
import pandas as pd
dict = {"Sato": ["M", 165, 65],
"Yoshida": ["F", 175, 50],
"Kato": ["M", 160, 60],
"Abe": ["F", 150, 60]}
df = pd.DataFrame(dict, pd.Index(["Gender", "Height", "Weight"], name="Name")).T
df
# Name Gender Height Weight
# Sato M 165 65
# Yoshida F 175 50
# Kato M 160 60
# Abe F 150 60
辞書からのDataFrame
生成法については、次の記事を参照してください。
まずは、.sort_index()
メソッドで、インデックス(行ラベル)をもとにソートしてみましょう。
df_sorted = df.sort_index()
print(df_sorted)
# Name Gender Height Weight
# Abe F 150 60
# Kato M 160 60
# Sato M 165 65
# Yoshida F 175 50
インデックス(Name
)が昇順(A → Z)の順番になるように、並べ替えられましたね。
次に、.sort_values()
メソッドで、データ列をもとにソートしてみます。
df_sorted = df.sort_values("Height")
print(df_sorted)
# Name Gender Height Weight
# Abe F 150 60
# Kato M 160 60
# Sato M 165 65
# Yoshida F 175 50
引数で指定した"Height"
列が、昇順(小さい数値→大きい数値)の順に並べ替えられましたね。
単純な並べ替えであれば、.sort_index()
, .sort_values()
メソッドを実行するだけでOKです。
以下では、追加の引数を指定して、並べ替えの細かな設定を行う方法について解説していきます。
主要な設定方法は、.sort_index()
, .sort_values()
メソッドで共通している部分が多いため、区別せずに解説していきます。
並べ替えの追加設定一覧
追加設定に使用できる主要な引数を、次の表にまとめました。
設定内容 | 引数名 | 適用 |
---|---|---|
並べ替え基準列指定 | by="列名" |
.sort_values() の必須引数 |
複数列で並べ替え | by=["列名1", "列名2", …] |
.sort_values() の場合 |
並べ変えインデックス指定 | level=インデックスレベル or 名前 |
マルチインデックスでない場合省略可能 |
マルチインデックスで並べ替え | level=["インデックス1", "インデックス2", …] |
.sort_index() の場合 |
昇順・降順 | ascending=True or False |
True : 昇順False : 降順 |
欠損値の配置 | na_position="last" or "first" |
"last" :末尾(デフォルト)"first" :先頭 |
ソート方向 | axis=0 or 1 |
0 : 列方向(デフォルト) 1 : 行方向 |
DataFrame上書き | inplace=False or True |
False : 新規DataFrame 生成(デフォルト), True : 既存DataFrame 上書き |
ソート時関数適用 | key=関数 |
指定した順番にソートする際に使用(後述) |
以下では、各設定について詳しく解説していきます。
ソート列の指定|by
データ列をもとにソートする場合は、.sort_values()
に列名を与えます。
.sort_values("列名")
or.sort_values(by = "列名")
by
は省略可能なので書かないことの方が多いと思います。
実行例を確認してみましょう。
# "Gender"列で並べ替え
df.sort_values("Gender") # df.sort_values(by = "Gender")と同じ
# Name Gender Height Weight
# Yoshida F 175 50
# Abe F 150 60
# Sato M 165 65
# Kato M 160 60
# "Height"列で並べ替え
df.sort_values("Height")
# Name Gender Height Weight
# Abe F 150 60
# Kato M 160 60
# Sato M 165 65
# Yoshida F 175 50
簡単ですね。デフォルトでは、データは昇順で並べ替えられます。
インデックスでソート|level
インデックスで並べ替えする場合には、.sort_index()
メソッドを使用します。
df.sort_index()
# Name Gender Height Weight
# Abe F 150 60
# Kato M 160 60
# Sato M 165 65
# Yoshida F 175 50
もしマルチインデックスの場合は、level
引数でインデックスを指定できます。
level
引数にインデックスレベル
または"インデックス列名"
を与えます。
df.sort_index(level=インデックスレベル)
ordf.sort_index(level="インデックス列名")
インデックスレベルは、外側のインデックスから連番で0
, 1
,…となっています。
次のマルチインデックスのサンプルデータで挙動を確認してみましょう。
my_data = [["Sato", "M", 165, 65],
["Yoshida", "F", 175, 50],
["Kato", "M", 160, 60],
["Abe", "F", 150, 60]]
df = pd.DataFrame(my_data, columns=pd.Index(["Name", "Gender", "Height", "Weight"]))
df_mul = df.set_index(["Name", "Gender"])
df_mul
# Height Weight
# Name Gender # NameとGenderのマルチインデックスDataFrame
# Sato M 165 65
# Yoshida F 175 50
# Kato M 160 60
# Abe F 150 60
リストからのDataFrame生成方法について、次の記事を参考にして下さい。
"Gender"
インデックスで並べ替えてみましょう。
df_mul.sort_index(level=1)
# df_mul.sort_index(level="Gender")でも同じ
# Height Weight
# Name Gender
# Abe F 150 60
# Yoshida F 175 50
# Kato M 160 60
# Sato M 165 65
インデックスの設定方法・基本操作、次の記事を参照してください。
昇順・降順|ascending
デフォルトでは、データは昇順で並べ替えられます。
- A → Z
- あ → ん
- 小さい数字 → 大きい数字
昇順・降順の設定は、ascending
で指定可能です。
- 昇順:
ascending = True
- 降順:
ascending = False
実行例を確認してみましょう。
# 昇順で並べ替え(デフォルト)
df.sort_values("Height") # ascending=Trueがデフォルト
# Name Gender Height Weight
# Abe F 150 60
# Kato M 160 60
# Sato M 165 65
# Yoshida F 175 50
# 降順で並べ替え(ascending=Falseの指定)
df.sort_values("Height", ascending=False)
# Name Gender Height Weight
# Yoshida F 175 50
# Sato M 165 65
# Kato M 160 60
# Abe F 150 60
欠損値の配置|na_position
データ内に欠損値がある場合は、デフォルトではデータの末尾に配置されます。
欠損値の位置を変更したい場合は、na_position
で指定します。
- 最初に配置:
na_position = "last"
(デフォルト) - 最後に配置:
na_position = "first"
次の欠損値を含むデータで挙動を確認してみましょう。
df_na = df.copy()
df_na.loc["Yoshida", "Weight"] = None
print(df_na)
# Name Gender Height Weight
# Sato M 165 65
# Yoshida F 175 None
# Kato M 160 60
# Abe F 150 60
上記のサンプルコード内のdf_na.loc["Yoshida", "Weight"] = None
のような各データへのアクセス方法については、次の記事を参照してください。
欠損値がある状態でのソートの挙動を確認してみましょう。
# デフォルト設定での並べ替え
df_sorted = df_na.sort_values("Weight")
print(df_sorted)
# Name Gender Height Weight
# Kato M 160 60
# Abe F 150 60
# Sato M 165 65
# Yoshida F 175 None # <-デフォルトではNoneは最後に配置される
# 欠損値を先頭に配置(na_position="first")
df_sorted = df_na.sort_values("Weight", na_position="first")
print(df_sorted)
# Name Gender Height Weight
# Yoshida F 175 None # <- na_position="first"でNoneを先頭に配置
# Kato M 160 60
# Abe F 150 60
# Sato M 165 65
欠損値処理については、次の記事も参考にしてください。
行方向にソート|axis
行方向に並べ替えする場合には、axis
引数を指定します、
- 列方向にソート:
axis=0 or "index"
(デフォルト) - 行方向にソート:
axis=1 or "columns"
次のサンプルデータで挙動を確認してみましょう。
dict = {"Sato": ["M", 165, 65],
"Yoshida": ["F", 175, 50],
"Kato": ["M", 160, 60],
"Suzuki": ["F", 150, 60]}
df = pd.DataFrame(dict, pd.Index(["Gender", "Height", "Weight"]))
# Sato Yoshida Kato Suzuki
# Gender M F M F
# Height 165 175 160 150
# Weight 65 50 60 60
"Height"
行をもとに行方向でソートしてみます。
df.sort_values("Height", axis=1)
# Suzuki Kato Sato Yoshida
# Gender F M M F
# Height 150 160 165 175
# Weight 60 60 65 50
DataFrameを上書き|inplace
DataFrame
の多くのメソッドと同じで、.sort_values()
, .sort_index()
メソッドは、
もとのDataFrame
を書き換えずに、新たなDataFrame
を返します。
# 元のDataFrameの内容確認
df
# Name Gender Height Weight
# Sato M 165 65
# Yoshida F 175 50 …省略
# 並び替えで新たなDataFrame生成
df_sorted = df.sort_index()
df_sorted
# Name Gender Height Weight
# Abe F 150 60
# Kato M 160 60 …省略
# 元のDataFrameは変化なし
df
# Name Gender Height Weight
# Sato M 165 65
# Yoshida F 175 50 …省略
もともとのDataFrame
を上書きしたい場合は、inplace=True
を指定します。
# 元のDataFrameの内容確認
df
# Name Gender Height Weight
# Sato M 165 65
# Yoshida F 175 50 …省略
df.sort_index(inplace=True)
df
# Name Gender Height Weight
# Sato M 165 65
# Yoshida F 175 50 …省略
複数データでソート
複数列、複数インデックスでソートすることも可能です。
.sort_values()
, .sort_index()
で引数が次のように異なります。
df.sort_values(["列名1", "列名2", …])
df.sort_index(level = [インデックス1, インデックス2, …])
以下で、それぞれ詳しく解説していきます。
複数列でソート|by=[]
複数のデータをもとにソートする場合は、リストでデータ列を渡します。
df.sort_values(["列名1", "列名2", …])
列名1
を基準に並べ替えた後、"列名1"
が同じグループ内で"列名2"
で並べ替えられます。
実際に実行例を見てみると、挙動がよくわかると思います。
df.sort_values(["Gender", "Height"])
# Name Gender Height Weight
# Abe F 150 60
# Yoshida F 175 50
# Kato M 160 60
# Sato M 165 65
細かく挙動を見ていくと、次のような並べ替え処理になっています。
"Gender"列
で並べ替え"Gender" = "F, "M"
それぞれで、Height
で並べ替え
図にすると次のようになります。
各データ列で昇順降順を指定するには、次のように"列名"
と同じ順序でascending
を指定します。
df.sort_values(["Gender", "Height"], ascending=[True, False])
# Name Gender Height Weight
# Yoshida F 175 50
# Abe F 150 60
# Sato M 165 65
# Kato M 160 60
複数インデックスでソート|level=[]
マルチインデックスのデータの場合にも、複数のインデックス列を使用してソートすることが可能です。
level
引数にインデックスレベル
または"インデックス列名"
を与えます。
df.sort_index(level = [インデックスレベル1, インデックスレベル2, …])
- or
df.sort_index(level = ["インデックス列名1", "インデックス列名2", …])
インデックスレベルは、外側のインデックスから連番で0
, 1
,…となっています。
次のマルチインデックスのサンプルデータで実行例を見てみましょう。
my_data = [["Sato", "M", 165, 65],
["Yoshida", "F", 175, 50],
["Kato", "M", 160, 60],
["Abe", "F", 150, 60]]
df = pd.DataFrame(my_data, columns=pd.Index(["Name", "Gender", "Height", "Weight"]))
df_mul = df.set_index(["Name", "Gender"])
df_mul
# Height Weight
# Name Gender # NameとGenderのマルチインデックスDataFrame
# Sato M 165 65
# Yoshida F 175 50
# Kato M 160 60
# Abe F 150 60
まずはインデックスレベルを指定して、ソートしてみます。
df_mul.sort_index(level=[1, 0])
# Height Weight
# Name Gender
# Abe F 150 60
# Yoshida F 175 50
# Kato M 160 60
# Sato M 165 65
インデックスに名前が設定されている場合は、インデックス列名で指定することも可能です。
df_mul.sort_index(level=["Gender", "Name"])
# Height Weight
# Name Gender
# Abe F 150 60
# Yoshida F 175 50
# Kato M 160 60
# Sato M 165 65
指定した順番にソート|key
昇順・降順以外にも特定の順番でソートしたい場合もあるかと思います。
例えば、都道府県名で並べ替えなどですね。
そういった場合は、"key"
引数に並べ替え用の関数を渡します。
並べ替え関数は、次のような引数・出力の関数にします。
def func_name(ソート基準列のSeries):
# ソート基準列のSeriesを、
# ソート可能なSeriesに変換する処理
# 例えば、都道府県名 → 1~47の数字
return ソート可能なSeries
次のサンプルデータを都道府県名をもとに並べ替えしてみましょう。
dict = {"Sato": ["M", 165, 65, "Aomori"],
"Yoshida": ["F", 175, 50, "Iwate"],
"Kato": ["M", 160, 60, "Miyagi"],
"Suzuki": ["F", 150, 60, "Hokkaido"]}
df = pd.DataFrame(dict, pd.Index(["Gender", "Height", "Weight", "Birth"])).T
# Gender Height Weight Birth
# Sato M 165 65 Aomori
# Yoshida F 175 50 Iwate
# Kato M 160 60 Miyagi
# Suzuki F 150 60 Hokkaido
まずは、都道府県名と番号を紐づけた辞書を用意します。
key_dict = {
"Hokkaido": 1,
"Aomori":2,
"Iwate": 3,
"Miyagi": 4}
次に都道府県名のSeries
を受け取って、対応する番号のSeries
を返す関数を作成します。
一つずつ処理しても良いですが、map()
関数で各要素に辞書を適用すればOKですね。
def ken2num(s):
return s.map(key_dict)
最後に、都道府県名で並べ替えしてみましょう。
df.sort_values("Birth", key = ken2num)
# Gender Height Weight Birth
# Suzuki F 150 60 Hokkaido
# Sato M 165 65 Aomori
# Yoshida F 175 50 Iwate
# Kato M 160 60 Miyagi
一行で書ける程度の関数なのでLambda式
でも十分そうです。
以下にテンプレを記載しておきます。
順序指定テンプレ(辞書)
辞書型で順序を指定する場合のテンプレは以下の通りです。
key_dict = {"変換前": "変換後", …}
df.sort_values("データ列", key = lambda s: s.map(key_dict.get) )
実行例は以下の通りです。
# 都道府県名→番号に変換する辞書
key_dict = {
"Hokkaido": 1,
"Aomori":2,
"Iwate": 3,
"Miyagi": 4}
# lambda関数で実行
df.sort_values("Birth", key = lambda s: s.map(key_dict.get) )
# Gender Height Weight Birth
# Suzuki F 150 60 Hokkaido
# Sato M 165 65 Aomori
# Yoshida F 175 50 Iwate
# Kato M 160 60 Miyagi
順序指定テンプレ(リスト)
リストで順序を指定する場合のテンプレは以下の通りです。
リストの場合は、並べ替えしたい順番にリスト要素を登録しておきましょう。
key_list = ["変換前要素1","変換前要素2", …]
df.sort_values("データ列", key = lambda s: s.map(key_list.get) )
実行例は以下の通りです。
# 都道府県名→番号に変換する辞書
key_list = ['Hokkaido', 'Aomori', 'Iwate', 'Miyagi']
# lambda関数で実行
df.sort_values("Birth", key = lambda s: s.map(key_list.index) )
# Gender Height Weight Birth
# Suzuki F 150 60 Hokkaido
# Sato M 165 65 Aomori
# Yoshida F 175 50 Iwate
# Kato M 160 60 Miyagi
[リスト]
の.index()
メソッドは要素がないとき、ValueError
になってしまうので注意が必要です。
オススメ|pandasとデータ分析の勉強方法
今回は、pandas
のソートについて解説しました。
pandas
は便利すぎて操作方法がわかりにくいことがよくあります…。
結局はコツコツ学ぶのが、pandas
マスターの近道ですよね!
データ分析初心者の方にはこちらの記事もおススメです。
私がこれまで勉強してきた経験をもとに考えたおススメの勉強本の紹介記事です。
何から始めて、どうやってレベルアップしていけばいいのか、初心者の方にぜひおススメしたい本を紹介しました。
オススメのpandas
本については、次の記事で紹介しています。