PythonでExcelの日付から曜日ごとの合計を出す手順|曜日の番号でまとめて月曜から並べる
Pythonのpandasで、Excelの売上の明細の日付から曜日を取り出し、曜日ごとの合計を月曜から日曜の順に並べて書き出す手順を解説します。曜日の名前で並びが崩れる理由や、売上の無い曜日が消える点も、架空のデータで試して紹介します。
目次
この記事でわかること
- 日付の列から、曜日の番号を取り出す方法(dt.day_of_week)
- 曜日ごとの売上の合計を、月曜から日曜の順に並べて書き出す方法
- 売上の無い曜日を0の行として残す方法(reindex)
- 曜日の名前でまとめると並びが崩れる理由と、古い書き方の警告
売上の明細に「曜日」の列を手で足して、曜日ごとの売上を出していませんか。並べ替えると金曜が先頭に来たり、定休日の曜日が表から消えたりすることもあります。この記事では、pandasで日付から曜日を取り出し、月曜から日曜の7行の表にして書き出すまでを順に見ていきます。
参考にしたのは、pandas 3.1.0の公式の資料(Series.dtのday_of_weekとday_name、Series.reindex、DataFrame.groupby、to_datetime)で、2026年10月31日に原文を読みました。明細の日付と金額は、説明のために作った架空のものです。
先に結論: 曜日を番号でまとめ、7行にそろえてから名前を付ける
dt.day_of_weekで曜日を番号(月曜が0、日曜が6)にし、その番号でgroupbyして合計します。 最後にreindexで0から6の7行にそろえ、売上の無い曜日を0で埋めてから、「月」「火」…の名前に置きかえます。
| 段階 | pandasの機能 |
|---|---|
| 日付の型にする | pd.to_datetime |
| 曜日の番号を取る | dt.day_of_week |
| 番号ごとに合計する | groupby |
| 月曜から日曜の7行にそろえる | reindex |
曜日の番号と名前の取り出し方
資料では、day_of_weekは曜日を数で返し、月曜を0、日曜を6とする、と説明しています。週は月曜に始まり、日曜で終わる前提です。
曜日の名前がほしいときはday_nameもあります。ただ、初期の設定では「Monday」のような英語の名前になります。名前のまままとめると並び順の問題が出るので、この記事では番号でまとめ、名前は最後に付けます。
売上の無い曜日を残す(reindex)
groupbyの結果には、明細に出てこない曜日の行がありません。定休日の日曜があると、合計の表は6行になります。
reindexは、渡した並びの行に表をそろえ、元に無かった行は空(NaN)にします。fill_valueを渡すと、空の代わりにその値で埋められます。0から6の番号を渡せば、どの曜日も1行ずつ、月曜から順に並びます。
手順: 売上の明細から曜日ごとの合計を書き出す
次のコードは、架空の明細 daily_sales.xlsx(日付・売上の2列)を読み、曜日ごとの合計を weekday_total.xlsx に書き出します。daily_sales.xlsx には書き込みません。ファイルの名前と列の名前は、手元の明細のものに置きかえて使います。
import pandas as pd
# 売上の明細を読む(元のファイルには書き込まない)
sales = pd.read_excel("daily_sales.xlsx")
# 日付の列を日付の型にする。読めない値は空(NaT)になるので、その数を出しておく
sales["日付"] = pd.to_datetime(sales["日付"], errors="coerce")
print("読めなかった日付の数:", sales["日付"].isna().sum())
# 曜日を番号で取り(月曜が0、日曜が6)、番号ごとに売上を合計する
sales["曜日番号"] = sales["日付"].dt.day_of_week
weekday = sales.groupby("曜日番号")["売上"].sum()
# 月曜から日曜の7行にそろえ、売上の無い曜日は0にしてから名前を付ける
weekday = weekday.reindex(range(7), fill_value=0)
weekday.index = ["月", "火", "水", "木", "金", "土", "日"]
weekday.index.name = "曜日"
print(weekday)
weekday.to_excel("weekday_total.xlsx")
このコードには、pandasのほかに、xlsxのファイルを扱うopenpyxlが要ります。先に入れておきます。
試した結果
2026年10月5日(月)から13日(火)までの売上を入れた、9行の架空の明細で動かしました。日付の1つは「2026/10/07」という文字で入れ、1行は日付の欄に「不明」と書きました。日曜(10月11日)は定休日として行を入れていません。
- 「読めなかった日付の数: 1」と出ました。「不明」の行です
- 曜日ごとの合計は、月22,000・火14,000・水9,000・木7,000・金15,000・土20,000・日0の7行で、月曜から順に並びました
- 文字で入れた「2026/10/07」の行も、水曜の9,000に入りました
- 「不明」の行の4,000は、どの曜日にも入っていませんでした。明細の合計91,000に対し、7行の合計は87,000です
- weekday_total.xlsx は、曜日と売上の2列・7行でした
- 元の daily_sales.xlsx のハッシュ値は、実行の前後で変わりませんでした
動かした環境は、作業用のMacに入れたPython 3.12.15と、pandas 3.1.0、openpyxl 3.1.5です。表をExcelのアプリで開いて見ることはしていません。
自分で直すか、相談するかの判断
目安は、「週を月曜から数えてよいか」と「1日の区切りが0時でよいか」の2つです。どちらもそのままでよければ、上のコードの列の名前を変えるだけで使えます。
日曜始まりで見せたい、深夜0時をまたぐ営業を前の日に数えたい、祝日を分けたい、といった決まりがあるときは、作りが変わります。報告を受け取る人と区切り方を決めてから作り、出した合計は手で数えた週の数字と一度照らし合わせます。
つまずきやすいところ
- 曜日の名前でまとめる: day_nameの名前でgroupbyすると、試した明細ではFriday・Monday・Saturday…という文字の順になり、月曜から並びませんでした
- reindexを外す: 試したときも、reindexの行を外すと、合計の表は日曜の無い6行になりました。定休日がある表では、0の行が要るかどうかを先に決めます
- 日付が文字のまま.dtを使う: to_datetimeで直さずにday_of_weekを使うと、「Can only use .dt accessor」で始まる例外が出て、そこで処理が止まりました。日付の直し方は、PythonでExcelの日付を正しく読み込む手順にまとめています
- dayofweekと書く: 古い書き方のdayofweekでも番号は同じでしたが、将来の版で消えるという警告が出ました。day_of_weekと書きます
- 月ごとの合計もほしい: 日付を年月にまとめる方法は、PythonでExcelの日付から月ごとの合計を出す手順で紹介しています
- 店舗ごと・曜日ごとの表にしたい: 行に店舗、列に曜日を並べる表は、PythonでExcelのピボットテーブルのように集計する手順の方法で作れます
まとめ
- 日付の列はpd.to_datetimeで直し、読めなかった行の数を確かめます
- dt.day_of_weekで曜日を番号にしてまとめると、月曜の0から日曜の6の順に並びます
- reindexで7行にそろえ、売上の無い曜日を0で残してから名前を付けます
- 古い書き方のdayofweekではなく、day_of_weekと書きます
よくある質問
曜日を「月曜日」のような日本語の名前で出せますか?
day_nameのlocaleに日本語の地域の設定を渡すと出せることがあります。資料では、初期の設定は英語で、使える設定の名前はUnixの端末でlocale -aを打って調べるとしています。試したMacでは"ja_JP.UTF-8"で「月曜日」と出ましたが、使える名前はパソコンによって違います。この記事のように、番号から名前を付ける方が環境に左右されません。
1日あたりの平均を曜日ごとに出したいときは?
合計を、その曜日の日数で割ります。期間の中に月曜が2回あれば、月曜の合計は2日分です。試した明細でも、月曜の22,000円は2日分で、1日あたりは11,000円でした。日数は、曜日の番号ごとに日付の重なりを除いた数(nunique)で数えられます。
dayofweekとday_of_weekは、どちらを使えばよいですか?
day_of_weekを使います。資料では、dayofweekはpandas 3.1.0で非推奨になり、day_of_weekを使うよう書かれています。試したときも、dayofweekを使うと、将来の版で消えるという警告が出ました。返す番号はどちらも同じでした。
日曜から土曜の順に並べたいときは?
reindexに渡す番号の並びを、日曜の6から始まる[6, 0, 1, 2, 3, 4, 5]に変え、名前の並びも日曜からにそろえます。試した明細でも、日曜の0円が先頭に来ました。
曜日の名前の列でまとめると、なぜ月曜から並ばないのですか?
groupbyは、初期の設定でまとめる値を並べ替えるためです。曜日の名前は文字なので、文字の順に並びます。英語の名前ならFridayが先頭になります。番号でまとめれば、月曜の0から日曜の6の順になります。