概要(datetime変換は「文字列の日付を“時系列のエンジン”に乗せる最初の一歩」)
pandasで日付・時刻を扱うときは、まず文字列をdatetime型へ変換します。datetimeにしておくと、並べ替え、差分計算、月別集計、リサンプリングなど“時系列ならでは”の強い機能がすべて正しく動きます。初心者は、pd.to_datetimeでの基本変換、format指定、エラー扱い(coerce)、タイムゾーン、列が分かれている場合の組み立てを押さえると迷いません。
基本の使い方(pd.to_datetimeで文字列→日時へ)
最小例(素直なISO形式を変換する)
import pandas as pd
df = pd.DataFrame({"date": ["2025-01-01", "2025-01-02", "2025-01-03"]})
df["date"] = pd.to_datetime(df["date"])
print(df.dtypes)
# date datetime64[ns]
Pythonまずはこれ。文字列のままだと辞書順でしか並べ替えできませんが、datetimeなら時系列の昇降順や差分計算が正しく動きます。
フォーマットが混在・曖昧なときの安全策(errors=”coerce”)
df = pd.DataFrame({"date": ["2025/01/01", "2025-01-02", "bad"]})
df["date"] = pd.to_datetime(df["date"], errors="coerce")
print(df)
# 変換できない値はNaN(欠損)になる → 後でdropnaやfillnaで処理可能
Python現実のデータはきれいじゃないことが多いです。coerceにすると“壊れた値”で落ちずに前へ進めます。
明確なフォーマットを指定して高速・正確に
df = pd.DataFrame({"date": ["01/02/2025", "12/31/2024"]})
df["date"] = pd.to_datetime(df["date"], format="%m/%d/%Y")
Python大量データではformat指定が効率的。誤解を避け、速度も上がります。
実務でよくあるパターン(日時分割・UNIX時刻・タイムゾーン)
日付と時刻が別々の列にある
df = pd.DataFrame({
"date": ["2025-01-01", "2025-01-02"],
"time": ["09:30", "18:15"]
})
dt = pd.to_datetime(df["date"] + " " + df["time"])
Python文字列結合してからto_datetimeに渡すのがシンプル。フォーマットが固定ならformatも併用できます。
UNIXエポック秒・ミリ秒からの変換
import pandas as pd
s = pd.Series([1735689600, 1735776000]) # 例: 秒
dt = pd.to_datetime(s, unit="s", utc=True).dt.tz_convert("Asia/Tokyo")
Pythonunitで秒やミリ秒を指定。グローバルなデータはまずUTCにしてからローカルへtz_convertするのが定石です。
タイムゾーン付き文字列を正しく扱う
s = pd.Series(["2025-01-01T00:00:00Z", "2025-01-01T09:00:00+09:00"])
dt = pd.to_datetime(s, utc=True) # まずUTCへ正規化
local = dt.dt.tz_convert("Asia/Tokyo") # 表示・集計用にJSTへ
Pythonタイムゾーンが混在しても、いったんUTCへ寄せると安全。比較・集計の一貫性が保てます。
時系列ならではの操作(並べ替え・差分・抽出・リサンプリング)
並べ替えと抽出の基本形
df = pd.DataFrame({
"date": pd.to_datetime(["2025-01-02", "2024-12-31", "2025-01-01"]),
"sales": [100, 120, 200]
})
df = df.sort_values("date")
recent = df.loc[df["date"] >= "2025-01-01"]
Pythondatetimeにしておけば、範囲抽出も文字列で直感的に書けます。
差分計算(滞在時間や経過時間)
df = pd.DataFrame({
"start": pd.to_datetime(["2025-01-01 09:00", "2025-01-01 10:00"]),
"end": pd.to_datetime(["2025-01-01 10:30", "2025-01-01 10:45"])
})
df["duration_min"] = (df["end"] - df["start"]).dt.total_seconds() / 60
PythonTimedeltaにしてからdt.total_secondsで必要な単位へ落とします。分・時間・日での集計が簡単です。
月別・日別に集計(resample)
daily = pd.DataFrame({
"date": pd.to_datetime(["2025-01-01","2025-01-02","2025-01-03"]),
"sales": [100, 120, 80]
}).set_index("date")
monthly_sum = daily.resample("M")["sales"].sum()
Python等間隔でないデータでも、インデックスを日時にしてresampleすれば期間ごとの集計が一瞬です。
重要ポイントの深掘り(前処理順・フォーマット・欠損・型の落とし穴)
前処理の順番が品質を決める
- 文字列のトリミングや正規化(strip/lower)を先に。
- 曖昧なデータはerrors=”coerce”で落とし、欠損は後で扱う。
- datetimeへ変換してから、並べ替え・フィルタ・集計を行う。
フォーマット指定の鉄則
- formatは「必ず合う」なら積極的に使う。誤検知を避け、速度も上がる。
- 混在フォーマットは一旦coerceで落としてから、残りを個別処理すると事故が減る。
欠損(NaT)を見逃さない
- 変換できない値はNaTになります。countが減る、差分でエラーになるなどの原因に。
- dropna(subset=[“date”])やfillnaでポリシーを決めてから先へ進む。
dtypeの確認とタイムゾーンの一貫性
- date列がobjectのままになっていないか、df.dtypesで確認。
- グローバルデータは“UTC統一→必要に応じて表示用TZ”が安全。混在TZのまま比較しない。
実践例(ログ前処理の型、JSTに揃えて日次レポート、カレンダー特徴量)
ログの時刻をUTC→JSTへ揃えて日次集計
import pandas as pd
df = pd.DataFrame({
"ts": ["2024-12-31T15:00:00Z", "2025-01-01T01:00:00Z"],
"value": [10, 20]
})
ts_utc = pd.to_datetime(df["ts"], utc=True)
ts_jst = ts_utc.dt.tz_convert("Asia/Tokyo")
daily = pd.DataFrame({"date": ts_jst.dt.date, "value": df["value"]})
report = daily.groupby("date", as_index=False)["value"].sum()
print(report)
Python時差を吸収してから集計すれば、日付またぎの誤差がなくなります。
曖昧フォーマットを安全に扱う
df = pd.DataFrame({"date": ["2025-01-01", "01/02/2025", "2025.01.03", "bad"]})
df["date"] = pd.to_datetime(df["date"], errors="coerce")
clean = df.dropna(subset=["date"]).sort_values("date")
Pythonまず落とし、残った“正しい日時”だけで分析を進めます。
年月日・曜日などの特徴量を追加
df = pd.DataFrame({"date": pd.to_datetime(["2025-01-01", "2025-01-02"])})
df["year"] = df["date"].dt.year
df["month"] = df["date"].dt.month
df["day"] = df["date"].dt.day
df["weekday"] = df["date"].dt.day_name() # 例: Wednesday
Pythonモデルやレポートで使いやすい派生列をdtアクセサから簡単に作れます。
まとめ(「まずto_datetime」。coerceで守り、formatで速く、TZはUTC統一が安全)
datetime変換は、時系列分析のドアです。pd.to_datetimeで文字列を日時へ変え、曖昧さはerrors=”coerce”で受け止め、確かなフォーマットにはformatを指定して速く正確に。タイムゾーンは一度UTCへ正規化してから必要なローカルへ。その上で、sort・差分・resample・dtアクセサを使えば、日次レポートも期間集計も“滑らかに”回り始めます。最初の一歩を丁寧に—そこから時系列の世界が開けます。
