この記事でわかること

  • 行の並びを変えずに、順位の列を足す方法(rank)
  • 大きい順にする指定と、同じ値の行の順位の付け方
  • 店舗ごとに1位から順位を付ける方法
  • 売上が空欄の行の扱いと、自分の表で使う前に確かめること

担当者の売上の表に順位を付けるとき、表を並べ替えてから1、2、3と手で打ち込んでいませんか。並べ替えると元の並びが崩れ、同じ売上の人がいると番号の付け方にも迷います。この記事では、元の並びのまま「全体の順位」と「店舗の順位」の列を足す手順を紹介します。

根拠にしたのは、pandas 3.1.0のSeries.rankとDataFrameGroupBy.rankの公式の説明で、2026年10月31日に原文を読みました。売上の表は、この記事のために作った架空のものです。

先に結論: ascending=Falseとmethod="min"を指定する

売上の列にrankを使い、ascending=Falseで大きい順に、method="min"で同じ売上を同じ順位にします。 店舗の中の順位は、groupbyで店舗に分けてからrankを使います。

同じ値の行の順位は、methodで変わります。試した表で、40万円の2人と、その次の30万円の3人に付いた順位は次のとおりです。

method 40万円の2人 30万円の3人
"average"(初期設定) 2.5位 5位
"min" 2位 4位
"dense" 2位 3位
"first" 2位・3位 4〜6位

rankのしくみ

pandasの資料では、rankは1からnまでの順位を計算するとしています。初期設定では、同じ値の行には、それらの順位の平均が付きます。

同じ値の行の扱いはmethodで選べます。"min"はそのグループで最も小さい順位、"dense"は"min"と同じ考え方で、次の値の順位を1つずつしか増やしません。"first"は、表に出てくる順に順位を付けます。

ascendingの初期設定は小さい順です。groupbyのrankの資料では、Falseにすると大きい値から1位になると説明しています。

手順: 全体と店舗ごとの順位の列を作る

次のコードは、架空の表 staff_sales.xlsx の「店舗」と「売上」から「全体の順位」と「店舗の順位」の列を作り、staff_sales_ranked.xlsx という別の名前で保存します。元の staff_sales.xlsx はそのまま残ります。

import pandas as pd

# 担当者別の売上の表を読む(順位を付けた表は別の名前で保存する)
table = pd.read_excel("staff_sales.xlsx")

# 売上の大きい順に1位から。同じ売上は同じ順位にする
overall = table["売上"].rank(ascending=False, method="min")
table["全体の順位"] = overall.astype("Int64")

# 店舗の中での順位
in_store = table.groupby("店舗")["売上"].rank(ascending=False, method="min")
table["店舗の順位"] = in_store.astype("Int64")

print(table)
print("順位が空の行:", table["全体の順位"].isna().sum())

table.to_excel("staff_sales_ranked.xlsx", index=False)

astype("Int64")は、順位を整数の列にするためです。空の行は空のまま残ります。xlsxの読み書きにはopenpyxlも要ります。

試した結果

担当者が8人だけの作り物の表で動かしました。本店は50万・30万・30万円・空欄、駅前店は40万・30万・20万・40万円です。

  • 全体の順位は、50万円が1位、40万円の2人が2位、30万円の3人が4位、20万円が7位になりました
  • 店舗の順位は、本店が1位・2位・2位、駅前店が1位・3位・4位・1位でした
  • 売上が空欄の本店の行は、全体の順位も店舗の順位も空になり、「順位が空の行: 1」と表示されました
  • 順位の列は、小数ではなく整数の列で書き出されました
  • 元の staff_sales.xlsx は、実行の前後でハッシュ値が変わりませんでした

作業PCはMacで、ライブラリの版はpandas 3.1.0とopenpyxl 3.1.5、Python本体は3.12.15です。書き出したファイルはExcelで開いておらず、表示の確認はしていません。

自分で直すか、相談するかの判断

目安は、「同じ値の人の順位を、どう決めるかを1文で言えるか」です。「同じ売上なら同じ順位で、次の人は人数の分だけ下がる」と言えるなら"min"、「次の人は1つ下」なら"dense"のように、言葉がそのまま指定になります。

同じ売上のときに件数や日付で上下を決める、といった決まりがある場合は、rankだけでは足りません。先に決まりの順に表を並べてから"first"を使うかどうかを、順位を使う人と相談して決めます。

つまずきやすいところ

  • 小さい順になる: 試したときも、ascendingを付けないと、50万円の人が7位、20万円の人が1位になりました。売上の順位なら、ascending=Falseを付けます
  • 同じ売上の順位が2.5位になる: methodを付けないと、40万円の2人は2.5位、30万円の3人は5位になりました。整数の順位にしたいなら、methodを指定します
  • 店舗に分けずに順位を付ける: 全体の順位を店舗の順位のつもりで使うと、駅前店の1位が全体の2位のままになります。店舗の中の順位はgroupbyで分けてから付けます
  • 上位の行だけを取り出したい: 順位の列ではなく、上位10件を別のファイルにしたいときは、PythonでExcelの表を並べ替えて上位の行を取り出す手順のほうが向いています
  • 順位と一緒に、店舗の中の割合も出したい: 店舗の合計に対する割合の列を足す方法は、PythonでExcelのグループごとの割合の列を作る手順で紹介しています
  • 順位の列を中央にそろえて見せたい: 書き出したファイルの列の幅や書式の整え方は、PythonでExcel書き出しの列の幅と数値の書式を整える手順にまとめています

まとめ

  • rankは、行の並びを変えずに順位を返します
  • 大きい順ならascending=False、同じ値の扱いはmethodで決めます
  • 店舗ごとの順位は、groupbyで分けてからrankを使います
  • 空の行は順位も空になるので、件数を数えて確かめます