pandas

【Pandas】DataFrameやSeriesで数か月後の日付を計算する

Pythonで月単位の日付計算をする場合、relativedeltaを使用すると便利だが、DataFrameやSeriesで使おうとするとエラーとなる。

そのため、lambda式で1行ずつ適用してやる必要がある。

また、月末の日付について、1か月後、2か月後なども求めたい場合、注意する必要がある。

Seriesで数か月後の日付を計算

import pandas as pd
from dateutil.relativedelta import relativedelta

# DataFrame作成
date1 = ["2020-1-1", "2020-1-5", "2020-2-3"]
df_date = pd.DataFrame(data={"date1": date1})
df_date["date1"] = pd.to_datetime(df_date["date1"], format="%Y-%m-%d")

# 2か月後の日付計算
df_date["date2"] = df_date["date1"].apply(lambda x: x + relativedelta(months=2))
print(df_date)
       date1      date2
0 2020-01-01 2020-03-01
1 2020-01-05 2020-03-05
2 2020-02-03 2020-04-03

計算速度的には、なるべくapplyは使いたくないが、月単位の計算をしたい場合は、使うしかない。

relativedeltaの引数monthsに負の値を指定すれば、「Xか月前」も計算可能。

また、x – relativedelta(months=1)とすることで1か月前を計算することも可能。

月単位計算の不可逆性

Xか月後を計算した値に対してXか月前を計算しても元に戻らない場合がある。

date = ["2020-1-29", "2020-1-30", "2020-1-31", "2020-5-31"]

df_date = pd.DataFrame(data={"date1": date})
df_date["date1"] = pd.to_datetime(df_date["date1"], format="%Y-%m-%d")

# 1か月後の日付を計算
df_date["date2"] = df_date["date1"].apply(lambda x: x + relativedelta(months=1))
# 計算した1か月後の日付について、の1か月前の日付を計算
df_date["date3"] = df_date["date2"].apply(lambda x: x + relativedelta(months=-1))
print(df_date)
       date1      date2      date3
0 2020-01-29 2020-02-29 2020-01-29
1 2020-01-30 2020-02-29 2020-01-29
2 2020-01-31 2020-02-29 2020-01-29
3 2020-05-31 2020-06-30 2020-05-30

1月30日、31日の1か月後は2月29日となる(2020年は閏年)。

5月31日の1か月後は6月30日となる。

これらの計算した1か月後の日付に対して、1か月前の日付に戻そうとすると、1月30日や1月31日は1月29日になり、5月31日は5月30日になる。

毎月28日以前であれば、この問題が発生することはないため、Xか月後を計算したりするのはそこまで問題にはならない。

月末の日付に対してXか月後を計算する必要がある場合、こういう事象が発生することを念頭に置いて計算するか、30日後などの日付を計算した方が良い。

1か月後の日付計算

なお、求めたい日付が1か月後の場合、1か月の日数を加算することでも1か月後の日付を求めることができる。

上記の方法でも月末問題は発生するので注意が必要。

2か月後や3か月後など、数か月後の日付を求めたい場合、上記の方法は使いにくいため、relativedeltaをlanbda式で1行ずつ適用することとなる。