Shifting DatetimeIndex by one year gives unexpected result

Viewed 233

I have a dataframe with a DatetimeIndex and would like to shift the dates by one year. I thought I could do so with df.index.shift(1, 'Y'), but then all dates pile up at the end of the year?

What I mean is this (using the example from the docs):

import pandas as pd
month_starts = pd.date_range('1/1/2011', periods=5, freq='MS')
print("Original:", month_starts)
print("Shifted :", month_starts.shift(1, 'Y'))

This code creates a DatetimeIndex with 5 dates and shifts these by one year. However, the output is

Original: DatetimeIndex(['2011-01-01', '2011-02-01', '2011-03-01', '2011-04-01',
              '2011-05-01'],
              dtype='datetime64[ns]', freq='MS')
Shifted : DatetimeIndex(['2011-12-31', '2011-12-31', '2011-12-31', '2011-12-31',
              '2011-12-31'],
              dtype='datetime64[ns]', freq=None)

The desired result of the shift would have been ['2012-01-01', '2012-02-01', '2012-03-01', '2012-04-01', '2012-05-01']. Am I misunderstanding what the function is supposed to do?

Comments:

  • The output of month_starts.shift(365, 'D')) is closer to the desired result, but not quite there because 2012 is a leap year.
  • pd.__version__: 1.3.0
1 Answers

You could use DateOffset as freq:

month_starts.shift(freq = pd.DateOffset(years = 1))

Gives:

DatetimeIndex(['2012-01-01', '2012-02-01', '2012-03-01', '2012-04-01',
              '2012-05-01'],
              dtype='datetime64[ns]', freq=None)

Note:

Use with caution. Leap day (Feb 29th) will be transformed into Feb 28th (as per comments).

Related