K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

read_csvで日付が解釈できずValueErrorになる

01.9.5

read_csvで日付が解釈できずValueErrorになる

最終更新 2025-11-04 読了時間 3 分
まとめ
ValueError: time data '31/12/2024 23:00' does not match format '%Y-%m-%d %H:%M' は、pandas が最初の数行から「年-月-日 時:分」の書式だと推定したのに、途中に「日/月/年」の行が現れて照合に失敗した、という報告です。書式が 1 種類なら parse_dates=["ordered_at"] に dayfirst=True を添えて読み込み時に datetime64 へ変換し、%Y/%m/%d %H:%M・%d-%b-%Y・%Y%m%d のように複数書式が混在するなら converters に書式を順に試す関数を渡します。いったん文字列で読んでから pd.to_datetime(errors="coerce", utc=True) で一括変換し、合わない値は NaT に落とす方法もあります。このページでは orders.csv の ordered_at 列を例に、3 つの方法の使い分けを示します。

直感 #

日付の文字列は 2024-12-31、31/12/2024、20241231、31-Dec-2024 のように何通りにも書けるので、pandas は先頭の値から書式を 1 つ推定し、その書式で全行を照合します。推定した書式と違う行が 1 つでもあれば does not match format で止まり、推定自体をあきらめた場合は列が object 型のまま残って df.sort_values が文字列順になったり diff() が失敗したりします。対処の方針は「書式を教える」「行ごとに複数の書式を試す」「合わない値は NaT にして先へ進む」の 3 つで、エラーメッセージに出た実際の値('31/12/2024 23:00')を見てどれを選ぶかを決めます。

日付列を含む CSV を読み込むとき、次のようなエラーメッセージが出ることがあります。

ValueError: time data '31/12/2024 23:00' does not match format '%Y-%m-%d %H:%M'

あるいは読み込み自体はできても、ordered_at が object 型のままで df["ordered_at"].dt.month が AttributeError になったり、sort_values が "1/2/2024" を "12/1/2023" より後ろに並べたりすることもあります。これは 日付フォーマットの推定が失敗している、または 混在した形式が存在する ためです。


解決法 1: parse_dates と日付フォーマットを指定する #

書式が 31/12/2024 23:00 の 1 種類に揃っているなら、parse_dates で列を指定し、日が先に来る欧州式であることを dayfirst=True で伝えると、読み込み時に datetime64[ns] 型になります。

1
2
3
4
5
6
7
8
import pandas as pd

df = pd.read_csv(
    "orders.csv",
    parse_dates=["ordered_at"],
    dayfirst=True,                   # 31/12/2024 のような形式
    infer_datetime_format=True,      # パターン推測を有効化
)

解決法 2: 独自フォーマットを converters で変換する #

2024/12/31 23:00、31-Dec-2024、20241231 のように複数の書式が同じ列に混ざっているときは、書式を 1 つずつ試す関数を自前で用意し、converters で読み込み時に適用します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from datetime import datetime

def parse_datetime(value: str):
    value = value.strip()
    for fmt in ("%Y/%m/%d %H:%M", "%d-%b-%Y", "%Y%m%d"):
        try:
            return datetime.strptime(value, fmt)
        except ValueError:
            continue
    return pd.NaT  # どれにも当てはまらなければ欠損扱い

df = pd.read_csv("orders.csv", converters={"ordered_at": parse_datetime})

解決法 3: 読み込み後に to_datetime で一括処理 #

いったん文字列として読み込み、pd.to_datetime で列をまとめて変換する方法です。errors="coerce" で合わない値を NaT にし、utc=True でタイムゾーンを揃えると、途中で止まらずに全行を処理できます。

1
2
3
4
5
6
7
df = pd.read_csv("orders.csv")
df["ordered_at"] = pd.to_datetime(
    df["ordered_at"],
    format="%Y-%m-%d %H:%M:%S",
    errors="coerce",   # 変換できなければ NaT
    utc=True,          # タイムゾーンを統一
)

使いどころと落とし穴 #

変換の前に、ordered_at に 2024/12/31 と 31-Dec-2024 のような複数の書式が混じっていないか、+09:00 のような時差情報が付いた値と付いていない値が混在していないかを df["ordered_at"].str.len().value_counts() で確認すると、文字数の違いとして書式のばらつきが見えます。Excel から書き出した表では 45657 のような日付のシリアル値が数値列として紛れ込むことがあり、これは pd.to_datetime(df["col"], unit="D", origin="1899-12-30") で日付に戻します。errors="coerce" や converters で NaT に落としたレコードは、集計で除外するのか、前後の値で埋めるのかを後続処理で決めておかないと、groupby の月別集計から黙って消えます。

参考 #

format・errors・utc の仕様は pandas.to_datetime — pandas documentation に、変換後の DatetimeIndex でできる resample やタイムゾーン操作は Time series / date functionality — pandas user guide にまとまっています。