Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pandas offset DatetimeIndex to next business if date is not a business day

Tags:

python

pandas

I have a DataFrame which is indexed with the last day of the month. Sometimes this date is a weekday and sometimes it is a weekend. Ignoring holidays, I'm looking to offset the date to the next business date if the date is on a weekend and leave the result unchanged if it is already on a weekday.

Some example data would be

import pandas as pd
idx = [pd.to_datetime('20150430'), pd.to_datetime('20150531'), 
       pd.to_datetime('20150630')]
df = pd.DataFrame(0, index=idx, columns=['A'])
df

            A
2015-04-30  0
2015-05-31  0
2015-06-30  0

df.index.weekday
array([3, 6, 1], dtype=int32)

Something like the following works, however I would appreciate if someone has a solution that is a little more straightforward.

idx = df.index.copy()
wknds = (idx.weekday == 5) | (idx.weekday == 6)
idx2 = idx[~wknds]
idx2 = idx2.append(idx[wknds] + pd.datetools.BDay(1))
idx2 = idx2.order()
df.index = idx2
df

            A
2015-04-30  0
2015-06-01  0
2015-06-30  0
like image 366
mgilbert Avatar asked Sep 29 '15 02:09

mgilbert


3 Answers

You can add 0*BDay()

from pandas.tseries.offsets import BDay
df.index = df.index.map(lambda x : x + 0*BDay())

You can also use this with a Holiday calendar with CDay(calendar) in case there are holidays.

like image 77
phil_20686 Avatar answered Oct 20 '22 00:10

phil_20686


You can map the index with a lambda function, and set the result back to the index.

df.index = df.index.map(lambda x: x if x.dayofweek < 5 else x + pd.DateOffset(7-x.dayofweek))

df
            A
2015-04-30  0
2015-06-01  0
2015-06-30  0
like image 33
matt_s Avatar answered Oct 19 '22 23:10

matt_s


Using DataFrame.resample

A more idiomatic method would be to resample to business days:

df.resample('B', label='right', closed='right').first().dropna() 

              A
2015-04-30  0.0
2015-06-01  0.0
2015-06-30  0.0
like image 24
Erfan Avatar answered Oct 20 '22 00:10

Erfan