YutaKaのPython教室

Python の文法やライブラリ、API、環境構築について画像・動画・ソースコード付きで徹底解説!

pandas 本当にわかりやすいソートの仕方|図解・サンプルあり!

pandasDataFrame, Sereisでは、データやインデックスをもとに並べ替え(ソート)が行えます。

しかし、実際にソートしようとすると、次のような問題に直面することも…

  1. データのソートには、どのメソッドを使うの?
  2. 昇順、降順の設定方法、
  3. 複数列で並べ替えはどうするの?

このような疑問を解決するため、この記事では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生成法については、次の記事を参照してください。

≫pandas 辞書型からDataFrameを生成|インデックスとコラムの設定も!
pandasでは、辞書型からデータフレームを生成することもできます。しかし、pandasの操作に慣れていないうちは、ちょっとした操作も難しいですよね。この記事では、①辞書型からデータフレームを生成する方法、②辞書のキーをインデックス名、コラム名それぞれに設定する方法、③DataFrame()とDataFrame.from_dict()の違いをサンプルコード付きで紹介!
www.yutaka-note.com/entry/pandas_dict
 

まずは、.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=インデックスレベル) or
  • df.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生成方法について、次の記事を参考にして下さい。

≫pandas リストからDataFrameを生成|インデックスとコラムの設定も!
pandasでは、リストからデータフレームを生成することもできます。しかし、pandasの操作に慣れていないうちは、ちょっとした操作も難しいですよね。この記事では、①リストからデータフレームを生成、行と列を追加する方法、②インデックス名、コラム名を設定する方法、③DataFrameを転値する方法(行と列が期待と逆だった時の対応)をサンプルコード付きで紹介!
www.yutaka-note.com/entry/pandas_list
 

"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

インデックスの設定方法・基本操作、次の記事を参照してください。

≫pandas DataFrameにインデックス設定|パターン別にわかりやすく解説
pandasのDataFrameでは、インデックス名でデータにアクセスします。しかし、DataFrameへのインデックス指定方法は少しわかりにくい部分も…。そこで、この記事では、パターン別に設定方法を解説!①DataFrame作成時にインデックス列指定、②既存DataFrameで指定、③ExcelやCSVから読み込み時に指定 ④インデックスの振り直し…
www.yutaka-note.com/entry/pandas_index_setting
 
≫pandas インデックス列の基本操作|要素にアクセス、検索、欠損値処理
pandasのDataFrameでは、インデックス列の操作方法に関して、網羅的に解説!①インデックスの基本構造②インデックス内要素へのアクセス方法③インデックス内のデータ検索、並べ替え、重複処理、欠損値処理。サンプルコード付きでわかりやすく解説!
www.yutaka-note.com/entry/pandas_index_manip
 

昇順・降順|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のような各データへのアクセス方法については、次の記事を参照してください。

≫pandas DataFrameの行・列を抽出|loc, ilocなどわかりやすく解説!
pandasのDataFrameを使うと、行と列で構成されたデータを簡単に取り扱うことができます。この記事では、「DataFrameの特定の行、列のデータを抽出する方法」、「インデックス参照、.loc、.iloc、at、iat[]の使い方」をわかりやすい図解付きで解説しています。
www.yutaka-note.com/entry/pandas_access
 

欠損値がある状態でのソートの挙動を確認してみましょう。

# デフォルト設定での並べ替え
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

欠損値処理については、次の記事も参考にしてください。

≫pandas 欠損値NaN処理一覧|抽出、除去、補間
pandasを使用すると欠損値NaNを効率的かつ高速に処理することができます。① NaNのある行や列を抽出する方法は?② NaNのある行や列を削除したい!③ NaNを他の値で置き換えたり、線形補間したりするにはどうするの?こんな悩みをサンプルコート付きでわかりやすく解決します!
www.yutaka-note.com/entry/pandas_na
 

行方向にソート|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

細かく挙動を見ていくと、次のような並べ替え処理になっています。

  1. "Gender"列で並べ替え
  2. "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】

データ分析初心者の方にはこちらの記事もおススメです。

私がこれまで勉強してきた経験をもとに考えたおススメの勉強本の紹介記事です。

何から始めて、どうやってレベルアップしていけばいいのか、初心者の方にぜひおススメしたい本を紹介しました。

≫独学でデータ分析を勉強するオススメ学習本
独学でのpythonデータ分析勉強に役立ったおススメ書籍を紹介していきます。業務でそれなりにデータ分析を行えるまで、いろいろな試行錯誤をしてきましたが、もし自分が今ゼロから勉強する立場ならどうするのがいいのか考えてみました。以下では、入門書、個別モジュール用、実践用の3つの視点でおススメ本を紹介していきます。
www.yutaka-note.com/entry/data_analysis
 

オススメのpandas本については、次の記事で紹介しています。

≫【レビュー】「Python実践データ分析100本ノック」|100本終えたらpandasが好きになっていた
Python実践データ分析100本ノックで、実際に100本終了したレビューです。pythonでのデータ分析の入門書としてかなりの良書だったと思います。・python2~3冊目に何を勉強しようか迷っている人・時間をかけずにデータ分析の基本を学びたい人・pandasへの抵抗を減らしたい人
www.yutaka-note.com/entry/nock_100
 
≫【レビュー】「Pythonによるデータ分析入門」| pandas開発者によるpandasユーザーのためのpandasの教科書!
「Pythonによるデータ分析入門」を、最初から最後まで実際に実践してみたレビューです。具体的にどのようなことができるようになったかを実例付きで紹介します!・DataFrameの生成方法・欠損値の処理方法・グラフ化の方法気になる学習時間は…?
www.yutaka-note.com/entry/2019/12/07/230219