この記事でわかること

  • 受付日時の列から、何時台かを表す0〜23の数を取り出す方法(dt.hour)
  • 時間帯ごとの件数を数え、0時台から23時台まで24行の表にする方法
  • 件数の無い時間帯を、0の行として表に残す方法
  • 四捨五入でまとめると時間帯がずれる理由と、時刻だけの列の扱い方

問い合わせや注文の明細から「何時ごろに多いか」を知りたいとき、受付日時を目で追って時間帯ごとに数えるのは手間がかかります。この記事では、pandasで受付日時から時を取り出し、時間帯ごとの件数を24行の表にして書き出すまでを、手元で試した結果を添えて順にまとめます。

よりどころにしたのは、pandas 3.1.0の公式の資料(Series.dtのhour・round・floor、Series.value_counts、Series.reindex、Series.idxmax、pandas.to_datetime)です。原文は2026年11月3日に読みました。受付日時と件数は、試すために作った架空の明細のものです。

先に結論: dt.hourで時を取り出し、value_countsで数えて24行にそろえる

受付日時をpd.to_datetimeで日時の型に直し、dt.hourで時を取り出してvalue_countsで数えます。 そのままでは件数の多い順に並び、件数の無い時間帯は出てこないので、reindexで0から23の24行にそろえ、無い時間帯を0で埋めます。

やること 使うもの 試した明細での結果
日時の型にそろえる pd.to_datetime(errors="coerce") 17行のうち1行が空(NaT)
何時台かを取り出す dt.hour 0から23の数
時間帯ごとに数える value_counts 件数のある11の時間帯
24行にそろえる reindex(range(24), fill_value=0) 24行で合計16件

dt.hourとvalue_countsのしくみ

pandasの資料では、dt.hourは日時の値ごとに「時」の部分を返し、値は0から23の24時間の表し方になる、と説明しています。9時45分の受付なら9、23時50分なら23です。分の部分は使われないので、9時0分から9時59分までが同じ「9時台」になります。

value_countsは、値ごとの件数を数えます。資料のとおり、結果は件数の多い順に並び、最初の行がいちばん多い値です。空の値は初めの設定では数えません。どの時間帯が多いかを見るには便利ですが、0時から順に並べて見たいときや、件数の無い時間帯も表に残したいときは、次のreindexが要ります。

件数の無い時間帯を0で残す(reindex)

reindexに行の並びを渡すと、表がその並びに組み直されます。元の表に無かった行の値はNaNです。fill_valueを指定しておけば、NaNではなくその値で埋まります。range(24)の0から23を渡せば、受付が1件も無かった時間帯も0件の行として残り、0時台から23時台まで順に並びます。

手順: 受付の明細から時間帯ごとの件数を書き出す

次のコードは、架空の受付の明細 uketsuke.xlsx(受付日時・内容の2列)を読み込み、時間帯ごとの件数を hourly_count.xlsx に書き出します。uketsuke.xlsx には何も書き込みません。ファイルの名前と列の名前は、手元の明細に合わせて書きかえます。

import pandas as pd

# 問い合わせの受付の明細を読む(元のファイルには書き込まない)
calls = pd.read_excel("uketsuke.xlsx")

# 受付日時を日時の型に直す。日時として読めない値はNaTになるので、その行数を出す
calls["受付日時"] = pd.to_datetime(calls["受付日時"], errors="coerce")
print("日時として読めなかった行:", calls["受付日時"].isna().sum())

# 時(0〜23)を取り出して件数を数え、0時台から23時台の24行に並べ直す
hour = calls["受付日時"].dt.hour
hourly = hour.value_counts().reindex(range(24), fill_value=0)
hourly.index = [f"{h}時台" for h in hourly.index]
hourly.index.name = "時間帯"
hourly.name = "件数"

print(hourly.idxmax(), hourly.max())   # いちばん多い時間帯とその件数
print("数えた件数:", hourly.sum())     # 明細の行数から読めなかった行を引いた数と比べる
hourly.to_excel("hourly_count.xlsx")

pandasでxlsxのファイルを読み書きするには、openpyxlも入れておく必要があります。最後の「数えた件数」を、明細の行数から読めなかった行を引いた数と見比べると、数え漏れがないかを確かめられます。

試した結果

2026年10月5日と6日の2日分の、17行の架空の受付の明細で動かしました。受付日時は9時台と10時台に多く、0時10分・8時45分・17時59分・23時50分の受付も入れました。1行は「2026/10/06 16:20」という文字で入れ、もう1行は受付日時の欄に「不明」と書きました。

  • 「日時として読めなかった行: 1」と表示されました。「不明」と書いた行です
  • いちばん多い時間帯は「10時台 4」で、9時台が3件で続きました
  • 文字で入れた「2026/10/06 16:20」の行も、16時台の1件に数えられました
  • 8時45分は8時台、17時59分は17時台、23時50分は23時台に入りました
  • 「数えた件数: 16」と出ました。17行から読めなかった1行を引いた数と同じです
  • hourly_count.xlsx は、時間帯と件数の2列・24行で、0時台から23時台まで並んでいました。件数の無い13の時間帯は0です
  • 元の uketsuke.xlsx は、実行の前と後でハッシュ値が同じでした

試したのはMacの作業PCで、Python本体が3.12.15、pandasが3.1.0、openpyxlが3.1.5でした。Excelのアプリでは開いておらず、書き出したファイルの中身はopenpyxlで読み直して確かめました。

自分で数えてよいか、相談するかの判断

目安は、「明細の受付日時が、問い合わせの来た時刻そのものか」です。電話やフォームの受付の時刻がそのまま記録されているなら、上のコードの列の名前を変えるだけで使えます。

担当者が後でまとめて入力した時刻や、メールを読んだ時刻が入っている明細では、数えた時間帯が実際の混み方とずれます。どの時刻を記録しているかを、明細を作っている人に確かめてから数えます。夜の0時をまたいで営業する窓口で、深夜の受付を前の日の分に数えたいといった決まりがあるときも、先に数え方を決めておきます。

つまずきやすいところ

  • 件数の多い順に並び、無い時間帯が出ない: value_countsだけで止めると、試した明細では10時台・9時台が先頭に来て、件数のある11の時間帯しか並びませんでした。0時台から順に24行で見たいときは、reindexまで続けます
  • 「10.0時台」のように小数が付く: 日時として読めない行があると、dt.hourの結果は小数の列になりました。reindexを通さずに名前を付けると、「10.0時台」のような名前になります。reindex(range(24))の後なら、0から23の整数の名前になりました
  • dt.roundで時間帯にまとめる: dt.round("h")は近いほうの時刻に丸めるため、8時45分が9時台、17時59分が18時台、23時50分は翌日の0時台に入りました。何時台かを数えるときは、分を切り捨てるdt.hour(またはdt.floor("h"))を使います
  • 日付と時刻が別の列になっている: 時刻だけの列は、試したときも日時の型ではなく時刻のまま読み込まれ、.dtを使うと「Can only use .dt accessor」で始まる例外が出ました。pd.to_datetimeでerrors="coerce"を付けると、例外は出ないかわりに5行すべてがNaTになりました。日付の列と時刻の列を文字にしてつないでから、pd.to_datetimeで直します
  • 曜日ごとの傾向も見たい: 日付から曜日を取り出して月曜から並べる方法は、PythonでExcelの日付から曜日ごとの合計を出す手順で紹介しています
  • 月ごとの件数の移り変わりを見たい: 日付を年月にまとめて集計する方法は、PythonでExcelの日付から月ごとの合計を出す手順にまとめています
  • 曜日と時間帯の組み合わせで数えたい: 曜日を行、時間帯を列に並べた件数の表は、PythonでExcelの2つの項目の組み合わせごとに件数を集計する手順のcrosstabで作れます

まとめ

  • 受付日時をpd.to_datetimeで日時の型に変え、NaTになった行がいくつあるかを先に見ます
  • dt.hourで時を取り出してvalue_countsで数え、reindexで0時台から23時台の24行にそろえます
  • 何時台かを数えるときは、四捨五入のdt.roundではなく、分を切り捨てるdt.hourを使います
  • 数えた件数の合計を、明細の行数から読めなかった行を引いた数と見比べます