PythonでExcelの表を指定順に並べ替える手順|小・中・大や地域など決めた順番で並べる
Excelの表を、小・中・大や地域の順のように自分で決めた順番で並べ替える手順を、pandasの順番つきの区分(Categorical)で解説します。順番に無い値・同じ値の行の並び・逆順でつまずく点を、架空の注文の一覧で試しました。
目次
この記事でわかること
- 小・中・大のような、自分で決めた順番で行を並べ替える方法
- 列の値はそのままにして、並べ替えの基準だけに順番を付ける書き方
- 決めた順番に無い値や空欄の行が、どこに並ぶか
- 同じ値の行の並びを、読み込んだ順のままにする指定
注文の一覧をサイズの小・中・大の順に、支店の一覧を北から南の地域の順に並べたい場面があります。毎月同じ並べ方をくり返すなら、順番の一覧をコードに書いておくと、手順がぶれません。この記事では、pandasで注文の一覧を読み込み、決めた順番に並べた表を別のファイルに書き出すまでを、手元で試した結果と一緒に説明します。
参照したのは、pandas 3.1.1の公式の資料(順番つきの区分のユーザーガイド、pandas.Categorical、DataFrame.sort_values)と、3.0.0のリリースノートで、2026年11月5日に原文で確かめました。注文番号やサイズは、どれも試すために作った架空の値です。
先に結論: 並べ替えの基準だけを、順番つきの区分にする
sort_valuesのkeyに、決めた順番の一覧から作った順番つきの区分(Categorical)を返す関数を渡すと、その順番で並びます。 列の値そのものは変えないので、順番に無い値も書き出すファイルに残ります。
| したいこと | 書き方 | 架空の注文の一覧での結果 |
|---|---|---|
| 決めた順番に並べる | sort_values("サイズ", key=関数, kind="stable") | 小5行・中6行・大6行の順 |
| 順番に無い値を確かめる | ~列.isin(順番の一覧) | LL・「大 」・空欄の3行 |
| 逆の順番に並べる | ascending=False を足す | 大・中・小の順 |
| 順番に無い行を先頭に出す | na_position="first" を足す | 3行が先頭に |
順番つきの区分(Categorical)のしくみ
pandasの順番つきの区分は、値と、取りうる値の一覧(categories)を組にして持ちます。資料では、順番は値の文字の並びではなく、categoriesの並びで決まると説明しています。orderedをTrueにすると、並べ替えのときにcategoriesの順を守ります。
categoriesを渡したときに一覧に無い値は、資料の説明ではNaNに置きかえられます。ただし、pandas 3.0.0のリリースノートで、一覧に無い値を含むまま区分を作ることは非推奨になりました。試した3.1.1でも、そのまま作ると「将来はエラーにする」という警告が出ました。この記事のコードでは、一覧にある値だけを残してから区分にしています。
並べ替えのsort_valuesには、並べる前の値に関数をかけるkeyと、同じ値の並びを保つ並べ方を選ぶkindがあります。資料では、kindのstableとmergesortだけが、同じ値どうしの元の順番を保つとしています。空の値の位置はna_positionで決まり、初めの設定は最後です。
手順: 注文の一覧をサイズの小・中・大の順に並べて書き出す
次のコードは、架空の注文の一覧 chumon.xlsx を読み込み、サイズの列を小・中・大の順に並べた表を chumon_narabi.xlsx に書き出します。元の chumon.xlsx は書きかえません。名前の付いた3か所(ファイル・列・順番の一覧)は、手元の表に合わせて書きかえます。なお、コードの最初の3行で順番と読み込みを決めています。
import pandas as pd
junban = ["小", "中", "大"] # 並べたい順番
chumon = pd.read_excel("chumon.xlsx") # 読むだけで、上書きはしない
# 決めた順番に無い値の行を、先に画面で確かめる
nai = chumon.loc[~chumon["サイズ"].isin(junban), ["注文番号", "サイズ"]]
print("順番に無い値の行:", nai.values.tolist())
def jun(s):
# 順番にある値だけを順番つきの区分にする(無い値は空になり、後ろに並ぶ)
kubun = pd.Categorical(s.where(s.isin(junban)), categories=junban, ordered=True)
return pd.Series(kubun, index=s.index)
narabi = chumon.sort_values("サイズ", key=jun, kind="stable")
print(narabi.to_string(index=False))
narabi.to_excel("chumon_narabi.xlsx", index=False)
関数junが返す区分は並べる順番を決めるためだけに使い、表のサイズの列はそのまま残ります。kind="stable"は、同じサイズの行を読み込んだ順のまま並べるための指定です。Excelのファイルを開いて保存するところは、pandasの中でopenpyxlが受け持つので、あわせて入れておきます。
試した結果
注文番号・地域・サイズの3列で、データの行が20行の架空の注文の一覧で動かしました。サイズは小5行・中6行・大6行のほか、順番の一覧に無いLLが1行、末尾に空白の入った「大 」が1行、空欄が1行です。
- 「順番に無い値の行: [['C-06', 'LL'], ['C-13', '大 '], ['C-17', nan]]」と表示されました
- 並んだ表の先頭は小の5行で、注文番号はC-02・C-07・C-10・C-15・C-19と、読み込んだ順のままでした
- 小の後に中の6行、大の6行が続き、最後にLL・「大 」・空欄の3行が並びました
- chumon_narabi.xlsx は3列・20行で、LLと「大 」もそのままの値で書き出されていました
- chumon.xlsx のハッシュ値は、動かす前と後で変わっていませんでした
動かしたのは手元のMacで、pandasは3.1.1、Pythonは3.12.15、openpyxlは3.1.5です。書き出した表は、openpyxlで開き直して中身を見ました。Excelのアプリでは開いていません。
順番の一覧を自分で決めてよいか、相談するかの判断
目安は、「その順番が、表を読む人のあいだで決まっているかどうか」です。サイズの小・中・大のように誰が見ても同じ順番なら、コードの一覧に書いて使ってかまいません。
地域や部署の並びのように、資料ごとに順番が違うことがある場合は、先に表を読む人と並びを決めておきます。新しい値が増えたとき(サイズにLLが加わる、支店が増えるなど)は、一覧に無い値の行が画面に出るので、そのときにどこへ入れるかを相談します。
つまずきやすいところ
- ふつうに並べると、思った順番にならない: keyを付けずにsort_valuesで並べると、先頭がLLで、その後に中・大・小の順になりました。文字の番号の小さい順に並ぶためで、小・中・大の意味は使われません
- 列そのものを区分に変えると、値が消える: サイズの列をそのまま順番つきの区分に変えると、LLと「大 」が空になり、書き出したファイルからも値が消えました。3.1.1では、非推奨の警告も出ました。列は変えずに、keyの関数の中だけで区分にします
- 末尾の空白で、順番に無い値になる: 「大 」は「大」と別の値として扱われ、一覧に無い行として最後に並びました。空白を取ってから並べる手順は、文字の前後の空白と全角・半角をそろえる記事にあります
- 同じ値の行の並びが崩れる: kindを付けないと、小の5行の先頭がC-10になり、読み込んだ順が崩れました。kind="stable"を付けると、C-02から順に並びました
- 逆に並べても、一覧に無い行は後ろのまま: ascending=Falseで大・中・小の順になっても、LL・「大 」・空欄の3行は最後に残りました。先頭に出すときは、na_position="first"を付けます
- 値の大きい順に並べたい: 売上や点数のような数の列なら、順番の一覧は要りません。PythonでExcelの表を並べ替えて上位の行を取り出す手順のsort_valuesだけで並びます
- 曜日の順に並べたい: 日付から曜日を出して月曜から並べるなら、曜日の番号を使うPythonでExcelの日付から曜日ごとの合計を出す手順のやり方もあります
まとめ
- 決めた順番で並べるには、順番の一覧から作った順番つきの区分を、sort_valuesのkeyで渡します
- 列の値は変えずに、keyの関数の中だけで区分にすると、一覧に無い値も残ります
- 一覧に無い値と空欄は後ろに並ぶので、並べる前にisinで確かめます
- 同じ値の行を読み込んだ順に保つには、kind="stable"を付けます
よくある質問
並べ替えた表を書き出すときに、元のExcelのファイルは変わりますか?
変わりません。並べ替えた表を chumon_narabi.xlsx という別の名前で保存するだけです。試したときも、元の chumon.xlsx のハッシュ値は実行の前後で同じでした。
大・中・小のように、決めた順番の逆に並べたいときは?
sort_valuesにascending=Falseを足します。試した一覧では大・中・小の順になり、順番に無い値の3行は、逆にしても後ろのままでした。後ろに残る行を先頭に出したいときは、na_position="first"を付けます。
「中」以上のサイズの行だけを選べますか?
順番つきの区分にした列なら、「>= "中"」で中と大の行を選べます。試した一覧では12行が選ばれました。文字のままの列で同じ比べ方をすると、文字の番号の大小で比べるため、小の行まで選ばれてしまいました。
地域の順で並べ、同じ地域の中はサイズの順にしたいときは?
sort_valuesの並べる列に地域とサイズを並べて渡し、keyの関数の中で、列の名前に合わせて順番の一覧を切りかえます。試した一覧では、北海道の小の注文が先頭になりました。
順番の一覧に無い値は、どこに並びますか?
空(NaN)と同じ扱いになり、初めの設定では表の最後に並びます。試した一覧では、LL・末尾に空白のある「大 」・空欄の3行が最後でした。並べる前に、isinで一覧に無い値を確かめておくと見落としません。