ふくふくHukuhuku Inc.
EP.04Prep 8分公開: 2026-05-10

型変換:日付・数値・カテゴリの落とし穴

「2025/01/01」「2025-1-1」「Jan 1, 2025」「令和7年元日」── 同じ日付がこの世には何百通り存在する。型変換の地雷集。

#型変換#日付
CO📔 Google Colab で開く(上から順にセルを実行)
シェア

型変換は最初に通る関門で、最もバグが潜む箇所。「日付パース」「数値化」「カテゴリ型」それぞれに固有の罠があります。

日付パースの罠 5 選

  • フォーマット混在:`2025/01/01`, `2025-1-1`, `Jan 1, 2025`, `令和7年元日` ── 同じ日
  • タイムゾーン:UTC か JST か、システム依存。ナイーブ datetime は禁忌
  • 夏時間(DST):欧米データで「9 月の最終日曜深夜 1:30 が 2 回ある」事故
  • Unix epoch:秒 / ミリ秒 / マイクロ秒で 1000 倍ズレる
  • 和暦:令和 → 2019/05/01 開始、ライブラリによって扱いが違う

数値型の罠

  • `int` vs `int64`:オーバーフロー(10 億超は注意)
  • `float` の精度:`0.1 + 0.2 != 0.3`、金額は Decimal か整数で
  • NaN / Inf の伝染:1 つ NaN が混じると平均・SUM が NaN になる
  • 文字列 → 数値:`'1,234'` の `,` は事前除去、`'1.5万'` も対処要

カテゴリ型

  • 順序付き vs 順序なし:「小 < 中 < 大」は順序付き、「赤 / 青 / 緑」は順序なし
  • 未知カテゴリ:学習データにない値が推論時に来たらどうするか
  • メモリ削減:pandas の `category` 型は文字列のメモリを大幅削減

ツール別比較

ツール型変換強み
pandas`astype()`、`pd.to_datetime()`柔軟、エラー詳細
Polars`cast()`速い、エラーで停止
`safe_cast()`失敗時 NULL(事故防止)

Python 実装:日付パース 6 形式を統一

混在した日付フォーマットを 1 関数で吸収
Python
import pandas as pdfrom datetime import datetimeimport re
def parse_jp_date(s: str) -> pd.Timestamp | None:    """日本語データに頻出する日付フォーマットを吸収"""    if pd.isna(s) or s == "":        return pd.NaT
    # 和暦の正規化(令和 → 西暦)    if "令和" in s:        m = re.search(r"令和(\d+)年", s)        if m:            year = 2018 + int(m.group(1))            s = re.sub(r"令和\d+年", f"{year}年", s)    if "平成" in s:        m = re.search(r"平成(\d+)年", s)        if m:            year = 1988 + int(m.group(1))            s = re.sub(r"平成\d+年", f"{year}年", s)
    # 全角数字 → 半角    s = s.translate(str.maketrans("0123456789", "0123456789"))
    # pandas の柔軟パーサーに委ねる    try:        return pd.to_datetime(s, errors="coerce")    except Exception:        return pd.NaT
# テストtest_cases = [    "2025/01/01",    "2025-1-1",    "Jan 1, 2025",    "令和7年元日",  # → 2025-01-01    "令和7年1月1日",    "2025年1月1日",    "202501/01",  # 全角数字]for s in test_cases:    print(f"{s!s:25}{parse_jp_date(s)}")
タイムゾーンの罠
Python
import pandas as pd
# ナイーブ datetime(タイムゾーン不在)は禁忌naive = pd.Timestamp("2026-01-01 09:00:00")print(naive.tz)  # → None(不安)
# 必ず明示的にjst = pd.Timestamp("2026-01-01 09:00:00", tz="Asia/Tokyo")utc = jst.tz_convert("UTC")print(jst, "==", utc)  # 2026-01-01 09:00 JST == 2026-01-01 00:00 UTC
# DataFrame 全体にdf["created_at"] = pd.to_datetime(df["created_at"], utc=True)  # 全列 UTC に統一df["created_at_jst"] = df["created_at"].dt.tz_convert("Asia/Tokyo")
数値型の罠:金額の精度
Python
from decimal import Decimal
# float の精度問題print(0.1 + 0.2 == 0.3)        # False !!!print(0.1 + 0.2)                # 0.30000000000000004
# 金額は Decimal か整数(円単位)でamount = Decimal("1234.56")total = amount * 3print(total)  # 3703.68(誤差なし)
# pandas で金額列を扱うときdf["amount"] = df["amount"].astype("string").map(Decimal)
カテゴリ型のメモリ削減
Python
import pandas as pd
# 数百万行の文字列列をカテゴリ型にdf["status"] = df["status"].astype("category")print(df.memory_usage(deep=True))# 文字列列が 80 MB → カテゴリ化で 8 MB(10 倍削減)
# 順序付きdf["size"] = pd.Categorical(    df["size"],    categories=["S", "M", "L", "XL"],    ordered=True,)df["size"] > "M"  # → ブール列で「L 以上」が取れる

ふくふくの進め方

型変換で本番事故を起こした」のご相談には、ログ分析 → 型仕様書 → 共通変換関数化を 1〜2 週間で。型エラーで失敗するのが正解で、サイレントに変換し続ける設計は事故の元です。

次回予告

EP.05 は文字列正規化。「ふくふく」「フクフク」「FUKUFUKU」を統一する Unicode 正規化と日本語固有処理。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp