Code Sample, a copy-pastable example if possible
import pandas as pd
from pandas.tseries.offsets import *
rng = pd.date_range('2012-01-05', '2012-01-10', freq=BDay())
index = pd.DatetimeIndex(rng)
print(index)
index2 = index + pd.Timedelta('1D')
print(index2)
Problem description
The line index + pd.Timedelta('1D')
adds 1 day to a DatetimeIndex that has freq='B'
but the returned index contains non-business days:
DatetimeIndex(['2012-01-06', '2012-01-07', '2012-01-10', '2012-01-11'], dtype='datetime64[ns]', freq='B')
Please note that the freq
property is B
.
This behavior is very inconsistent:
- Why isn't freq
considered when performing computation (+/- Timedelta) on the DatetimeIndex?
- Why freq
doesn't reflect the actual data contained in the DatetimeIndex? ( it says 'B' even though it contains non-business days)
Expected Output
DatetimeIndex(['2012-01-05', '2012-01-06', '2012-01-09', '2012-01-10'], dtype='datetime64[ns]', freq='B') DatetimeIndex(['2012-01-06', '2012-01-09', '2012-01-10', '2012-01-12'], dtype='datetime64[ns]', freq='B')
Output of pd.show_versions()
Comment From: chris-b1
The freq
attribute is meant to be purely descriptive, so it doesn't and shouldn't impact calculations. Potentially docs could be clearer.
The 2nd one would be a bug, but when I run you code (Win 64, py36, pandas 0.22) I get a repr without a freq.
In [183]: index2 = index + pd.Timedelta('1D')
In [184]: index2
Out[184]: DatetimeIndex(['2012-01-06', '2012-01-07', '2012-01-10', '2012-01-11'], dtype='datetime64[ns]', freq=None)
In [185]: index2.freq
Comment From: chris-b1
And you may already know this, but if you want to date math confirming to a frequency, you add the actual offsets themselves:
In [187]: index + pd.offsets.BDay()
Out[187]: DatetimeIndex(['2012-01-06', '2012-01-09', '2012-01-10', '2012-01-11'], dtype='datetime64[ns]', freq='B')
Comment From: luca-s
@chris-b1 thank you for your help. I guess the only issue is the documentation then. It's hard to grasp what freq is about, what is the scope of its usage.
Thank you also for the suggested solution but unfortunately it doesn't solve the general problem of adding a Timedelta to an index. What if you want to add Timedelta('1D4h5m') to a DatetimeIndex that has a specific frequency? I don't believe there is a solution then, but this is out of topic here.
Again,thank you very much for your reply.
Comment From: jreback
@luca-s you simply want to use an offset; it does not have to be the same freq as an index. a Timedelta
is a fixed-offset object, IOW it simply adds/subtracts the actual datetimes, it is equivalent of a 'D' freq.
In [7]: index = pd.date_range('2012-01-05', '2012-01-10', freq='B')
In [8]: index
Out[8]: DatetimeIndex(['2012-01-05', '2012-01-06', '2012-01-09', '2012-01-10'], dtype='datetime64[ns]', freq='B')
In [9]: index + pd.offsets.BDay(1)
Out[9]: DatetimeIndex(['2012-01-06', '2012-01-09', '2012-01-10', '2012-01-11'], dtype='datetime64[ns]', freq='B')