言いたいこと
pd.tseries.offsets.DateOffset.__mul__
は使わない方が良い。
経緯
pandasでは、日時を扱うためにpd.Timestamp
というクラスが用意されています。また、ある日時からある期間離れた日時を計算したい時は pd.tseries.offsets.DateOffset
を使います。
今回は、pd.tseries.offsets.DateOffset
の面白い振る舞いを紹介します。
まずは、以下の実行結果を見てください。
$ python -m timeit -u msec -n 10 -s "import pandas as pd" "pd.Timestamp('2010-01-01 00:00:00') + 100 * pd.tseries.offsets.DateOffset(seconds=1)"
10 loops, best of 3: 0.438 msec per loop
$ python -m timeit -u msec -n 10 -s "import pandas as pd" "pd.Timestamp('2010-01-01 00:00:00') + 1000 * pd.tseries.offsets.DateOffset(seconds=1)"
10 loops, best of 3: 3.85 msec per loop
$ python -m timeit -u msec -n 10 -s "import pandas as pd" "pd.Timestamp('2010-01-01 00:00:00') + 10000 * pd.tseries.offsets.DateOffset(seconds=1)"
10 loops, best of 3: 41.9 msec per loop
何が言いたいかわかりますか?
DateOffsetに掛け算しただけ実行時間が線形に増えています。
多分ですが、内部で pd.Timestamp.__add__
が掛け算した回数だけ呼ばれています。
同じことをやるにはこうすると良いです。
$ python -m timeit -u msec -n 10 -s "import pandas as pd" "pd.Timestamp('2010-01-01 00:00:00') + pd.tseries.offsets.DateOffset(seconds=1*100)"
10 loops, best of 3: 0.0328 msec per loop
$ python -m timeit -u msec -n 10 -s "import pandas as pd" "pd.Timestamp('2010-01-01 00:00:00') + pd.tseries.offsets.DateOffset(seconds=1*1000)"
10 loops, best of 3: 0.0373 msec per loop
$ python -m timeit -u msec -n 10 -s "import pandas as pd" "pd.Timestamp('2010-01-01 00:00:00') + pd.tseries.offsets.DateOffset(seconds=1*10000)"
10 loops, best of 3: 0.0336 msec per loop
高速(というか、直感的に当たり前の挙動)になりました。
ちなみに、python標準モジュールのdatetimeを使うとこうなります。非常に高速です。
$ python -m timeit -u msec -n 10 -s "import datetime" "datetime.datetime(2010,1,1) + 100 * datetime.timedelta(seconds=1)"
10 loops, best of 3: 0.0031 msec per loop
$ python -m timeit -u msec -n 10 -s "import datetime" "datetime.datetime(2010,1,1) + 1000 * datetime.timedelta(seconds=1)"
10 loops, best of 3: 0.00276 msec per loop
$ python -m timeit -u msec -n 10 -s "import datetime" "datetime.datetime(2010,1,1) + 10000 * datetime.timedelta(seconds=1)"
10 loops, best of 3: 0.00227 msec per loop