pandasのソート|sort_valuesとsort_indexの違い、Series・DataFrameの並べ替えと列名・MultiIndexの並べ替え

pandasでのソートは、値で並べるならsort_values()、インデックス(行ラベル・列名)で並べるならsort_index()を使います。SeriesもDataFrameも同じ名前のメソッドで、降順はascending=False、DataFrameで基準の列を選ぶときはby(第1引数)に列名を渡します。

この記事では、SeriesとDataFrameで書き方がどう違うかを中心に、列名の並べ替え(axis=1)、value_counts()やgroupby()の結果の並べ替え、MultiIndexのソート、欠損値と同順位の扱いまでを、実行結果つきで整理します。コードはPython 3.12とpandas 3.0.6で実行しました(2026年10月15日確認)。決まった順番(「高・中・低」など)で並べたい場合は、pandasの並べ替えと任意の順番でのソートでkeyやカテゴリ型を使う方法を解説しています。

sort_valuesとsort_indexの違い

メソッド 何を基準に並べるか Series DataFrame
sort_values() 値 s.sort_values()(基準は1つしかないので指定不要) df.sort_values("列名")(基準の列を指定)
sort_index() インデックス(行ラベル)や列名 s.sort_index() df.sort_index()で行、axis=1で列名

どちらも元のデータは変えずに、並べ替えた新しいオブジェクトを返します。並べ替えた結果を使うには、変数に代入してください(後述)。主な引数は次のとおりで、両方のメソッドでほぼ共通です(sort_values、sort_indexの公式リファレンスより)。

引数 既定値 意味
by (sort_valuesのみ) 基準にする列名、または列名のリスト
ascending True Trueで昇順、Falseで降順。列ごとにリストで指定も可
axis 0 0で行を並べ替え、1で列を並べ替え
na_position “last” 欠損値(NaN)を末尾に置くか、”first”で先頭に置くか
kind “quicksort” 並べ替えの方式。”stable”か”mergesort”で同じ値の行の順番を保つ
ignore_index False Trueにすると結果のインデックスを0, 1, 2…に振り直す
key None 並べ替え前に値へ適用する関数(大文字小文字を無視するなど)
level (sort_indexのみ) MultiIndexのどの階層で並べるか

Seriesを並べ替える

Seriesは値の列が1本しかないので、sort_values()に列名を渡す必要はありません。インデックスは値と一緒に移動します。

import pandas as pd

s = pd.Series([30, 10, 50, 20], index=["c", "a", "d", "b"])

print(s.sort_values())                  # 値で並べ替え(昇順)
print(s.sort_values(ascending=False))   # 値で並べ替え(降順)
print(s.sort_index())                   # インデックスで並べ替え

実行結果:

a    10
b    20
c    30
d    50
dtype: int64
d    50
c    30
b    20
a    10
dtype: int64
a    10
b    20
c    30
d    50
dtype: int64

この例ではたまたま値の順番とインデックスの順番が一致しているので、1つ目と3つ目が同じ結果になっています。一般には、sort_values()は値の小さい順、sort_index()はラベル(ここでは a, b, c, d)の順に並びます。

DataFrameを列の値で並べ替える

DataFrameでは、どの列の値で並べるかを第1引数(by)で指定します。複数の列を基準にするときはリストで渡し、先に書いた列が優先されます。ascendingもリストにすると、列ごとに昇順・降順を変えられます。

import pandas as pd

df = pd.DataFrame({
    "店舗": ["渋谷", "新宿", "池袋", "新宿", "渋谷"],
    "月": [2, 1, 1, 2, 1],
    "売上": [120, 300, 180, 250, 150],
})

print(df.sort_values("売上", ascending=False))
print(df.sort_values(["店舗", "月"], ascending=[True, False], ignore_index=True))

実行結果:

   店舗  月   売上
1  新宿  1  300
3  新宿  2  250
2  池袋  1  180
4  渋谷  1  150
0  渋谷  2  120
   店舗  月   売上
0  新宿  2  250
1  新宿  1  300
2  池袋  1  180
3  渋谷  2  120
4  渋谷  1  150

2つ目は「店舗の昇順、同じ店舗の中では月の降順」です。ignore_index=Trueを付けたので、左端の番号が0から振り直されています。付けない場合は元の行番号がそのまま残ります。

なお、日本語の文字列は読みの五十音順ではなく、文字コード(Unicode)の順に並びます。上の例で「新宿 → 池袋 → 渋谷」になっているのはそのためです。読み順にしたいときは、読みがなの列を作ってそれで並べ替えます。

行ラベル・列名で並べ替える(sort_index)

sort_index()は、何も指定しなければ行のインデックスで並べ替えます。axis=1を付けると、列名のアルファベット順に列を並べ替えます。

import pandas as pd

df = pd.DataFrame({"b": [1, 9], "c": [3, 4], "a": [5, 6]}, index=["y", "x"])

print(df.sort_index())          # 行のインデックス(y, x)を並べ替え
print(df.sort_index(axis=1))    # 列名(b, c, a)を並べ替え

# 特定の行の値で列を並べ替える
print(df.sort_values("x", axis=1))

実行結果:

   b  c  a
x  9  4  6
y  1  3  5
   a  b  c
y  5  1  3
x  6  9  4
   c  a  b
y  3  5  1
x  4  6  9

3つ目のようにsort_values()にもaxis=1があり、ある行(ここでは x 行)の値の小さい順に列を並べ替えられます。「列名をアルファベット順にしたい」ならsort_index(axis=1)、「ある行の値の順に列を並べたい」ならsort_values(行ラベル, axis=1)と覚えておくと迷いません。

集計結果(value_counts・groupby)を並べ替える

実務でソートをよく使うのは、集計した結果を並べるときです。value_counts()もgroupby()の集計も、結果はSeriesで返るので、Seriesのソートがそのまま使えます。

import pandas as pd

sales = pd.DataFrame({
    "商品": ["りんご", "みかん", "りんご", "ぶどう", "みかん", "りんご"],
    "個数": [3, 5, 2, 1, 4, 6],
})

# 値の出現回数:value_counts() は多い順に並んで返る
counts = sales["商品"].value_counts()
print(counts)
print(counts.sort_index())      # 商品名の順に並べ直す

# groupby の結果は Series。合計の大きい順に並べる
total = sales.groupby("商品")["個数"].sum()
print(total.sort_values(ascending=False))

実行結果:

商品
りんご    3
みかん    2
ぶどう    1
Name: count, dtype: int64
商品
ぶどう    1
みかん    2
りんご    3
Name: count, dtype: int64
商品
りんご    11
みかん     9
ぶどう     1
Name: 個数, dtype: int64

value_counts()は最初から多い順に並んでいるので、項目名の順で見たいときはsort_index()を使います。一方、groupby()の結果はグループのキー(ここでは商品名)の順に並んでいるので、合計の大きい順にしたいときはsort_values(ascending=False)を付けます。集計の書き方はgroupby()でデータを集計する方法を参考にしてください。上位の何件かだけ欲しいときは、並べ替えてからhead()を取るよりnlargest()・nsmallest()のほうが簡単です。

MultiIndexを並べ替える(level)

インデックスが「年」と「四半期」のように階層になっている(MultiIndex)場合、sort_index()は上の階層から順に並べ替えます。levelで優先する階層を変えたり、ascendingを階層ごとに指定したりできます。

import pandas as pd

df = pd.DataFrame({
    "年": [2026, 2025, 2026, 2025],
    "四半期": [1, 2, 2, 1],
    "件数": [10, 20, 30, 40],
}).set_index(["年", "四半期"])

print(df.sort_index())                                  # 年→四半期の順
print(df.sort_index(level="四半期"))                     # 四半期を優先
print(df.sort_index(ascending=[True, False]))           # 年は昇順、四半期は降順

実行結果:

          件数
年    四半期    
2025 1    40
     2    20
2026 1    10
     2    30
          件数
年    四半期    
2025 1    40
2026 1    10
2025 2    20
2026 2    30
          件数
年    四半期    
2025 2    20
     1    40
2026 2    30
     1    10

level="四半期"のときは四半期でまとめられ、同じ四半期の中は年の順になっています。これは既定のsort_remaining=Trueによって、指定しなかった階層でも続けて並べ替えるためです。MultiIndexは並べ替えておかないと、locで範囲を指定したときに警告やエラーになることがあるので、作ったら一度sort_index()しておくと安心です。

欠損値(NaN)と同じ値の順番

import pandas as pd
import numpy as np

s = pd.Series([10, np.nan, 30, 20])
print(s.sort_values())                       # NaNは最後
print(s.sort_values(na_position="first"))    # NaNを先頭に

df = pd.DataFrame({"名前": ["B", "A", "C", "D"], "点": [80, 90, 80, 90]})
# 同じ点の行は元の順番を保ったまま並べたい
print(df.sort_values("点", ascending=False, kind="stable"))

実行結果:

0    10.0
3    20.0
2    30.0
1     NaN
dtype: float64
1     NaN
0    10.0
3    20.0
2    30.0
dtype: float64
  名前   点
1  A  90
3  D  90
0  B  80
2  C  80
  • NaNは昇順でも降順でも、既定では末尾に置かれます。先頭にしたいときはna_position="first"を指定します。
  • 同じ値の行の順番は、既定の”quicksort”では保証されません。元の並び(ここでは90点の A と D)を保ちたいときはkind="stable"を指定します。公式リファレンスによると、DataFrameでkindが効くのは1列だけで並べ替えるときで、複数列を指定したときは使われません。

並べ替えたのに変わらない:代入とinplace

「sort_valuesしたのに元のDataFrameが並んでいない」というのは、いちばん多いつまずきです。

import pandas as pd

df = pd.DataFrame({"点": [70, 90, 80]})

result = df.sort_values("点", inplace=True)
print(result)          # inplace=True の戻り値は None
print(df)

df2 = pd.DataFrame({"点": [70, 90, 80]})
df2.sort_values("点")  # 代入しないと何も変わらない
print(df2)
df2 = df2.sort_values("点")
print(df2)

実行結果:

None
    点
0  70
2  80
1  90
    点
0  70
1  90
2  80
    点
0  70
2  80
1  90
  • sort_values()は新しいDataFrameを返すだけなので、df = df.sort_values(...)のように代入しないと元のデータは変わりません。
  • inplace=Trueを付けると元のデータが並べ替わりますが、戻り値はNoneです。df = df.sort_values(..., inplace=True)と書くと、dfがNoneになってしまいます。

どちらでも動きますが、メソッドを続けてつなげられる(df.sort_values("点").head(3)など)ことから、代入する書き方のほうが読みやすくおすすめです。

目的別の書き方まとめ

やりたいこと 書き方
Seriesを値の小さい順に s.sort_values()
Seriesを値の大きい順に s.sort_values(ascending=False)
DataFrameを1列で並べ替え df.sort_values("列名")
複数列で並べ替え df.sort_values(["列A", "列B"], ascending=[True, False])
行のインデックス順に戻す df.sort_index()
列名をアルファベット順に df.sort_index(axis=1)
並べ替え後に番号を振り直す ignore_index=True(またはreset_index(drop=True))
NaNを先頭に na_position="first"
同じ値の行の順番を保つ kind="stable"
大文字小文字を無視 key=lambda s: s.str.lower()

よくある質問

Q. sort_valuesとsort_indexはどう使い分けますか?

中身の値(売上や点数など)の大小で並べたいときはsort_values()、行ラベルや列名、日付のインデックスなどラベルの順に並べたいときはsort_index()を使います。並べ替えたあと元の行の順番に戻したいときも、sort_index()が使えます。

Q. Seriesのsort_valuesで列名を指定するとエラーになります。

Seriesには列が1本しかないので、基準の列を指定する引数(by)はありません。s.sort_values()のように引数なしで呼び、降順にしたいときはascending=Falseだけを指定します。

Q. 並べ替えたあと行番号が飛び飛びになります。

sort_values()は元のインデックスを残したまま並べ替えるためです。ignore_index=Trueを付けるか、並べ替えたあとにreset_index(drop=True)を呼ぶと、0から順に振り直せます。

Q. 日本語の列を五十音順に並べられますか?

そのままでは文字コード(Unicode)の順になり、漢字は読みの順には並びません。読みがなの列を用意し、その列でsort_values()するのが確実です。

まとめ

pandasのソートは「値ならsort_values()、ラベルならsort_index()」の2つだけです。Seriesは引数なしで、DataFrameは基準の列名を渡し、列を並べ替えたいときはaxis=1を使います。集計結果の並べ替え、MultiIndexのlevel指定、NaNと同順位の扱い、代入忘れとinplaceの戻り値の4点を押さえておけば、データ分析で並べ替えに困ることはほとんどなくなります。


pandas|データ整形・変換の関連記事

並べ替え・型変換・行列の追加削除など、データの形を整える操作の記事です。

pandas全体の使い方は「pandasの使い方を初心者向けに解説」でまとめています。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら