Python: pd.date_range, не соответствует тому, что он возвращает

#python-3.x #pandas #date #sequence #date-range

#python-3.x #pandas #Дата #последовательность #диапазон дат

Вопрос:

Привет, кто-нибудь может объяснить мне, почему Python ведет себя так, как показано ниже:

 import pandas as pd
sdate = pd.to_datetime('2020-01-31')
date_range = pd.date_range(start = sdate   pd.DateOffset(months=-3), 
                           end = sdate   pd.DateOffset(months=-1), freq = 'M')
  

приведенный выше объект date_range возвращает:

 DatetimeIndex(['2019-10-31', '2019-11-30', '2019-12-31'], dtype='datetime64[ns]', freq='M')
  

тогда, если я сдвинусь на один месяц вперед, как указано ниже:

 sdate = pd.to_datetime('2020-02-29')

date_range = pd.date_range(start = sdate   pd.DateOffset(months=-3), 
                           end = sdate   pd.DateOffset(months=-1), freq = 'M')
  

приведенный выше объект date_range теперь возвращает:

 DatetimeIndex(['2019-11-30', '2019-12-31'], dtype='datetime64[ns]', freq='M')
  

почему второй экземпляр возвращает только две даты и первые три даты?

Спасибо

Ответ №1:

Это была интересная находка, главным виновником freq = 'M' которой является «частота на конец месяца».

Проблема

Проблема в основном в том, что freq = 'M' будут отображаться только последние дни каждого месяца за указанный вами период, поэтому для первого случая мы имеем

 sdate = pd.to_datetime('2020-01-31')
date_range = pd.date_range(start = sdate   pd.DateOffset(months=-3), 
                           end = sdate   pd.DateOffset(months=-1), freq = 'M')
  

который будет оценивать

 start = '2019-10-31'
end   = '2019-12-31'
  

таким образом, диапазон между этими датами (включительно) равен
['2019-10-31', '2019-11-30', '2019-12-31']

теперь для второго случая

 sdate = pd.to_datetime('2020-02-29')

date_range = pd.date_range(start = sdate   pd.DateOffset(months=-3), 
                           end = sdate   pd.DateOffset(months=-1), freq = 'M')
  

Это будет равно

 start = '2019-11-29'
end   = '2020-01-29'
  

таким образом, даты, которые являются ПОСЛЕДНИМИ ДНЯМИ МЕСЯЦА ['2019-11-30', '2019-12-31'] , связаны с тем, что диапазон заканчивается на 2020-01-29 so 2020-01-31 , не включен в диапазон.

Решение

Хорошо .. это зависит от того, чего вы хотите достичь, но если ваши диапазоны дат рассчитаны на ежемесячной основе, и вас не волнует день, тогда рассмотрите возможность использования MonthEnd как

 import pandas as pd
from pandas.tseries.offsets import MonthEnd

sdate = pd.to_datetime('2020-02-29')

date_range = pd.date_range(start = sdate   pd.DateOffset(months=-3)   MonthEnd(0), 
                           end = sdate   pd.DateOffset(months=-1)   MonthEnd(0), 
                           freq = 'M')
  

что даст вам

 DatetimeIndex(['2019-11-30', '2019-12-31', '2020-01-31'], dtype='datetime64[ns]', freq='M')
  

Ответ №2:

У date_range есть параметр periods . Проще рассчитать дату начала, установить частоту в месяцы и 3. Дата начала может быть любым днем месяца. date_range возвращает интервалы времени.

  sdate=pd.Timestamp('2019-10-01')
 index=pd.date_range(start=sdate,periods=3,freq='M')
 print(index)
  

вывод:

  DatetimeIndex(['2019-10-31', '2019-11-30', '2019-12-31'], dtype='datetime64[ns]', freq='M')