PythonでExcelの表からグループごとに上位の行を取り出す手順|店舗ごとの売上トップ3をまとめて出す
Pythonのpandasで、Excelの売上の表から店舗ごとに上位3件の行をまとめて取り出す手順を、sort_valuesとgroupbyのheadで解説します。同じ売上の扱いや空欄の店舗の行など、つまずきやすい点も架空の表で試して紹介します。
目次
この記事でわかること
- 店舗のようなグループごとに、上位の行を取り出す方法(sort_valuesとgroupbyのhead)
- 並べ替えを忘れると、上位ではない行が出る理由
- 境目に同じ売上が並んだときと、店舗が空欄の行の扱い
- 取り出した表を、行の番号を付けずに保存する方法
店舗ごとに売上の上位3件を報告したいとき、Excelで店舗ごとにフィルターをかけ、並べ替えては上から3行ずつ写していませんか。この記事では、全部の店舗の上位の行を、pandasで一度に取り出すやり方をまとめます。
説明の元にしたのは、pandas 3.1.0の公式の資料(groupbyのheadとnlargest、sort_values、groupby)で、2026年10月31日に原文を確かめました。売上の表は、手順を見せるために作った架空のコーヒー豆の売上です。
先に結論: 店舗の中で売上の大きい順に並べてから、店舗ごとに先頭の行を取る
sort_valuesで店舗の中を売上の大きい順にし、groupbyのheadで店舗ごとに先頭の3行を取ります。 headは並べ替えをしないので、先に並べておくことが要になります。
試した表で取り出せた行は、次のとおりです(売上の単位は万円)。
| 店舗 | 上位3件(商品と売上) |
|---|---|
| 本店 | マンデリン 90、モカ 80、コロンビア 60 |
| 駅前店 | モカ 70、キリマンジャロ 55、ブレンド 40 |
groupbyのheadのしくみ
pandasの資料では、groupbyのheadを、グループごとに最初のn行を返す機能だと説明しています。返すのは元の表の一部の行で、元の行の番号と並びはそのまま残ります。
つまり、headが見るのは「グループの中で表の上にある行」です。売上の大きさは見ないので、売上の大きい順にするのはsort_valuesの役目です。sort_valuesには並べる列を複数渡せ、ascendingで列ごとに小さい順か大きい順かを選べます。
手順: 店舗ごとに上位3件の行を取り出す
次のコードは、架空の表 store_sales.xlsx の「店舗」「商品」「売上」から、店舗ごとに売上の上位3件の行を取り出し、store_top3.xlsx に保存します。元の表には書き込まず、結果は別のファイルにします。
import pandas as pd
# 店舗ごとの売上の表を読む(取り出した行は別のファイルに書く)
table = pd.read_excel("store_sales.xlsx")
# 店舗の中で売上の大きい順に並べ、店舗ごとに先頭から3行を取る
ranked = table.sort_values(["店舗", "売上"], ascending=[True, False])
top3 = ranked.groupby("店舗").head(3)
print(top3)
top3.to_excel("store_top3.xlsx", index=False)
ascendingの[True, False]は、店舗は小さい順、売上は大きい順という指定です。3の数字を変えると、取り出す件数が変わります。
試した結果
本店と駅前店の5件ずつに、店舗の欄が空欄の1件を足した、11行の作り物の表で動かしました。行は店舗が交互になるように並べ、駅前店にはブレンドとマンデリンの2つに同じ40万円を入れました。
- 取り出した表は6行で、本店・駅前店とも3行ずつ、売上の大きい順に並びました(上の表のとおり)
- 店舗の欄が空欄だったグアテマラの行は、結果に入りませんでした
- 取り出した行の番号は、元の表の番号(7、2、9、3、5、1)のままでした
- store_top3.xlsx には行の番号の列がなく、店舗・商品・売上の3列でした
- 元の store_sales.xlsx のハッシュ値は、実行の前後で同じでした
使ったのは作業用のMacで、Python 3.12.15にpandas 3.1.0とopenpyxl 3.1.5を入れています。Excelのアプリで開いた見た目は見ていません。
自分で直すか、相談するかの判断
目安は、「何で分けて、何の大きい順に、何件取るか」の3つを言えるかです。「店舗で分けて、売上の大きい順に、3件」と言えれば、上のコードの列の名前と数字を合わせるだけで使えます。
同じ売上が境目に並んだときに何件出すか、店舗が空欄の行をどう扱うかは、報告を受け取る人と先に決めておきます。決まりがないまま件数だけそろえると、毎回ちがう行が残ることがあります。
つまずきやすいところ
- 並べ替えずにheadを使う: 試したときも、並べ替えを外すと、本店はブレンド50・モカ80・キリマンジャロ30という表の上から3行になり、上位ではありませんでした
- 境目の同じ売上に気づかない: 駅前店の3位は、ブレンドとマンデリンが同じ40でした。試した表では表で先にあったブレンドが残りましたが、どちらを残すかを決めたいときは、nlargestのkeepや順位の列を使います。同じ値の順位の決め方は、PythonでExcelの表に順位の列を付ける手順で紹介しています
- 店舗が空欄の行が消える: groupbyは初期設定で、分ける列が空の行を除きます。試したときも、dropna=Falseを付けると、空欄の店舗も1つのグループとして7行になりました
- 表全体の上位がほしい: 店舗で分けずに上位を出すなら、PythonでExcelの表を並べ替えて上位の行を取り出す手順の方法で足ります
- 上位の行ではなく、店舗の中の割合を見たい: 店舗の合計に対する割合の列を足す方法は、PythonでExcelのグループごとの割合の列を作る手順にまとめています
まとめ
- 店舗の中で売上の大きい順に並べてから、groupbyのheadで店舗ごとに先頭の行を取ります
- headは並べ替えをしないので、並べ替えを忘れると上位ではない行が出ます
- 境目に同じ売上が並ぶときと、店舗が空欄の行の扱いは、先に決めておきます
- 保存するときは、index=Falseで行の番号を付けずに書き出します
よくある質問
下位の3件を出したいときは?
売上の並べ方を小さい順に変えます。sort_valuesのascendingを[True, True]にすると、店舗ごとに売上の小さい順に並び、headで下位の行が取れます。
同じ売上の行を、境目でどちらも残したいときは?
売上の列だけをgroupbyで分け、nlargestにkeep="all"を付けます。公式の資料では、allを選ぶと同じ値をすべて残し、結果がn件より多くなることがあるとしています。試した表でも、駅前店は4件になりました。
1位の行だけがほしいときは?
headに1を渡します。並べ替えた後なら、店舗ごとに売上がいちばん大きい行が1行ずつ残ります。
groupbyにsort=Falseを付けると、結果の並びは変わりますか?
headの結果は変わりません。公式の資料では、sortの指定はheadのような絞り込みには効かないとしています。結果の並びは、headの前に並べた順のままです。
順位の列を付けてから絞り込む方法もありますか?
あります。店舗ごとの順位の列を作り、3位までの行を残す方法です。同じ売上に同じ順位を付けられるので、同点の扱いを決めたいときに向いています。