Pandasで日付を扱う方法は、データ分析や時系列データ処理で非常に重要です。
Pandasは日付や時間の操作をサポートするために、datetime64[ns]
型とpd.Timestamp
,pd.DatetimeIndex
などの便利なクラスを提供しています。
以下に詳しく解説します。
目次
日付データの型
Pandasでは日付を次のように扱います。
pd.Timestamp
単一の日付や日時を表現するオブジェクト。
例:pd.Timestamp("2025-08-23 10:30:00")
pd.DatetimeIndex
日付の配列(インデックスとして使う場合によく利用)。
例:pd.date_range("2025-01-01", periods=5, freq="D")
datetime64[ns]
型
DataFrameの列に日付を持たせる際の内部表現。
文字列を日付に変換
文字列として読み込まれた日付をPandasで扱える形式に変換します。
import pandas as pd
# 1) 単一の文字列をTimestampに変換
t1 = pd.to_datetime("2025-08-23")
print("t1:", t1, type(t1))
# 2) 複数フォーマットの混在を一括変換(自動判別)
df = pd.DataFrame({"date_str": ["2025/08/23", "2025-08-24", "2025.08.25", "23-08-2025"]})
df["date_auto"] = pd.to_datetime(df["date_str"], dayfirst=False, errors="coerce") # 変換失敗はNaTに
print("\n--- 自動判別 ---")
print(df)
# 3) フォーマット指定(高速・厳密)
df["date_fmt"] = pd.to_datetime(df["date_str"], format="%d-%m-%Y", errors="coerce")
print("\n--- フォーマット指定 ---")
print(df)
# 4) CSV読み込み時に日付化(実務で便利)
from io import StringIO
csv = StringIO("""date,value
2025-01-01,100
2025-01-02,200
2025-01-15,150
2025-02-01,300
""")
df_csv = pd.read_csv(csv, parse_dates=["date"])
print("\n--- CSV parse_dates ---")
print(df_csv.dtypes)
print(df_csv)
日付の生成
pd.date_range
で一連の日付を簡単に生成できます。
import pandas as pd
# 1) 日次で7件
r1 = pd.date_range("2025-01-01", periods=7, freq="D")
print("日次:", r1)
# 2) 毎月月初(Month Start)
r2 = pd.date_range("2025-01-01", periods=6, freq="MS")
print("\n月初:", r2)
# 3) 毎週月曜日
r3 = pd.date_range("2025-01-01", periods=6, freq="W-MON")
print("\n毎週月曜:", r3)
# 4) 営業日(Business Day)
r4 = pd.date_range("2025-01-01", periods=10, freq="B")
print("\n営業日(B):", r4)
日付の要素抽出
Datetime列から「年」「月」「日」「曜日」などを取り出せます。
import pandas as pd
df = pd.DataFrame({
"date": pd.to_datetime(["2025-08-23", "2025-12-31", "2026-01-01", "2026-02-29"], errors="coerce")
})
df["year"] = df["date"].dt.year
df["month"] = df["date"].dt.month
df["day"] = df["date"].dt.day
df["weekday_num"] = df["date"].dt.weekday # 月曜=0
df["weekday_name"] = df["date"].dt.day_name() # 英語の曜日名
df["weekofyear"] = df["date"].dt.isocalendar().week # ISO週番号
df["is_month_end"] = df["date"].dt.is_month_end
df["quarter"] = df["date"].dt.quarter
print(df)
日付の演算
日付の差分やシフトも簡単にできます。
import pandas as pd
df = pd.DataFrame({
"date": pd.to_datetime(["2025-08-20", "2025-08-21", "2025-08-23", "2025-08-30"]),
"value": [10, 15, 20, 40]
})
# 1) 差分(連続する行の差)※日付列のdiffはTimedelta、数値列のdiffは数値
df["date_diff"] = df["date"].diff() # 前行との差(Timedelta)
df["value_diff"] = df["value"].diff() # 前行との差(数値)
# 2) シフト(前日/翌日相当の行参照)
df["value_prev"] = df["value"].shift(1)
df["value_next"] = df["value"].shift(-1)
# 3) 日付への加算(7日後)
df["date_plus_7d"] = df["date"] + pd.Timedelta(days=7)
# 4) 時間ベースのローリング集計(7日間の合計)
# まずDatetimeIndexを設定
ts = df.set_index("date")["value"].asfreq("D") # 欠損日はNaNのまま
roll_sum_7d = ts.rolling("7D").sum()
print("--- 元データ ---")
print(df)
print("\n--- 7日ローリング合計(欠損日はNaN)---")
print(roll_sum_7d)
インデックスとして日付を使う
時系列データではDatetimeIndexをインデックスにするのが便利です。
import pandas as pd
# サンプルの時系列データ(日次)
idx = pd.date_range("2025-01-01", "2025-03-15", freq="D")
ts = pd.Series(range(len(idx)), index=idx) # 値は 0,1,2,...
# 1) 部分文字列で抽出(2025年1月だけ)
jan = ts["2025-01"]
print("--- 2025年1月 ---")
print(jan.head(), " ... ", jan.tail())
# 2) 期間指定で抽出
period = ts["2025-02-10":"2025-02-20"]
print("\n--- 2025-02-10〜2025-02-20 ---")
print(period)
# 3) locで明示的に抽出
first_week = ts.loc["2025-01-01":"2025-01-07"]
print("\n--- 1/1〜1/7 ---")
print(first_week)
時間・タイムゾーン処理
時刻やタイムゾーンの操作も可能です。
import pandas as pd
# 1) タイムゾーンなしのTimestampを作成
t = pd.to_datetime("2025-08-23 12:00:00")
print("naive:", t, t.tzinfo)
# 2) Asia/Tokyoとしてローカライズ(ローカル時刻がJSTであると解釈)
t_tokyo = t.tz_localize("Asia/Tokyo")
print("tokyo:", t_tokyo, t_tokyo.tzinfo)
# 3) UTCに変換(同一瞬間の異なる表現)
t_utc = t_tokyo.tz_convert("UTC")
print("utc:", t_utc, t_utc.tzinfo)
# 4) Series/DatetimeIndexでも同様
idx = pd.date_range("2025-08-23 00:00", periods=3, freq="H")
s = pd.Series([1,2,3], index=idx)
s_tokyo = s.tz_localize("Asia/Tokyo")
s_ny = s_tokyo.tz_convert("America/New_York")
print("\n--- JST ---")
print(s_tokyo)
print("\n--- NY ---")
print(s_ny)
実用例(リサンプリング)
時系列データを日単位・月単位で集計できます。
import pandas as pd
# 日次の売上データ(穴あきも含む例)
sales = pd.Series(
[100, 200, 150, 300],
index=pd.to_datetime(["2025-01-01", "2025-01-02", "2025-01-15", "2025-02-01"])
)
# 1) 月次合計(M:月末締め)
monthly_sum = sales.resample("M").sum()
# 2) 週次平均(W:週末日曜日締め。W-MONで月曜締めに変更可能)
weekly_mean = sales.resample("W").mean()
# 3) 日次にアップサンプリングして前方埋め(asfreq+ffillの典型)
daily_ffill = sales.resample("D").ffill()
print("--- 原系列(日次・疎) ---")
print(sales)
print("\n--- 月次合計 ---")
print(monthly_sum)
print("\n--- 週次平均 ---")
print(weekly_mean)
print("\n--- 日次へアップ+前方埋め ---")
print(daily_ffill.head(20))
まとめ
Pandasで日付を扱う流れは以下の通りです。
- 文字列を
pd.to_datetime
で変換 - 日付要素を
.dt
で抽出 - 日付演算は
Timedelta
や.shift()
を利用 DatetimeIndex
を使って時系列処理- リサンプリングで集計や頻度変換
以上、PythonのPandasで日付を扱う方法についてでした。
最後までお読みいただき、ありがとうございました。