Количество месяцев между двумя датами, когда указана одна дата

Входная функция

Date1            
2019-01-23      
2020-02-01  

примечание: Тип Date1datetime64[ns].

Цель

Я хочу рассчитать разницу в месяце между столбцом Date1 и '2019-01-01'.

Попробуйте и исправьте

Я пробую ответы из этого поста , но это не удалось, как показано ниже:

df['Date1'].dt.to_period('M') - pd.to_datetime('2019-01-01').to_period('M') 
  • примечание: версия панд: 1.1.5

Вы преобразовали Date1 в фактический тип даты с помощью pd.to_datetime()?

Paulo Marques 15.12.2020 01:15

@PauloMarques не нужен, смотрите мое обновление.

Jack 15.12.2020 01:17

@ Джек - Значит, вы хотите игнорировать год и вычислять только разницу в месяце? Например, разница в месяцах между 01.02.2020 и 01.01.2019 равна «1»?

sharathnatraj 15.12.2020 01:34

@sharathnatraj нет, это должно закончиться год. Для вашего примера это будет 13.

Jack 15.12.2020 01:35
2
4
112
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Я думаю, что это должно работать:

date_ref = pd.to_datetime('2019-01-01')
df["mo_since_2019_01"] = (df.Date1.dt.year - date_ref.year).values*12 + (df.Date1.dt.month - date_ref.month)

month_delta = (date2.year - date1.year)*12 + (date2.month - date1.month)

выход:

       Date1  mo_since_2019_01
0 2019-01-23                 0
1 2020-02-01                13

Я не понимаю ваш ответ, кажется, он не соответствует моему вопросу.

Jack 15.12.2020 01:31

Пытаться:

rd = df['Date1'].apply(lambda x:relativedelta(x,date(2019,1,1)))
mon = rd.apply(lambda x: ((x.years * 12) + x.months))
df['Diff'] = mon

Вход:

        Date1
0  2019-01-23
1  2020-02-01
2  2020-05-01
3  2020-06-01

Выход:

       Date1  Diff
0 2019-01-23     0
1 2020-02-01    13
2 2020-05-01    16
3 2020-06-01    17

Пожалуйста, не забудьте включить необходимый импорт, я предполагаю: from dateutil.relativedelta import relativedelta и from datetime import date

Asmus 15.12.2020 08:47

С этим решением вам не потребуется дальнейший импорт, поскольку он просто вычисляет длину pd.date_range() между фиксированной датой начала и переменной датой окончания:

def relative_months(start, end, freq = "M"):
    if start < end:
        x = len(pd.date_range(start=start,end=end,freq=freq))
    else:
        x = - len(pd.date_range(start=end,end=start,freq=freq))
    return x

start = pd.to_datetime("2019-01-01")
df['relative_months'] = df['Date1'].apply(lambda end: relative_months(start, end, freq = "M"))

В вашем конкретном случае, я думаю, решение anon01 должно быть самым быстрым/благоприятным; мой вариант, однако, позволяет использовать общие строки частоты для смещений дат, таких как 'M', 'D', …, и позволяет вам специально обрабатывать крайний случай «отрицательных» относительных смещений (т. е. что произойдет, если ваша дата сравнения не раньше, чем все даты в Date1).

Ответ принят как подходящий

Ваше решение должно быть изменено путем преобразования периодов в целые числа, а для второго значения используется один список элементов ['2019-01-01']:

df['new'] = (df['Date1'].dt.to_period('M').astype(int) - 
             pd.to_datetime(['2019-01-01']).to_period('M').astype(int))
print (df)
       Date1  new
0 2019-01-23    0
1 2020-02-01   13

Если сравнить решения:

rng = pd.date_range('1900-04-03', periods=3000, freq='MS')
df = pd.DataFrame({'Date1': rng})  


In [106]: %%timeit
     ...: date_ref = pd.to_datetime('2019-01-01')
     ...: df["mo_since_2019_01"] = (df.Date1.dt.year - date_ref.year).values*12 + (df.Date1.dt.month - date_ref.month)
     ...: 
1.57 ms ± 8.18 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [107]: %%timeit
     ...: df['new'] = (df['Date1'].dt.to_period('M').astype(int) - pd.to_datetime(['2019-01-01']).to_period('M').astype(int))
     ...: 
1.32 ms ± 19.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

Применяем петли под капотом, так медленнее:

In [109]: %%timeit
     ...: start = pd.to_datetime("2019-01-01")
     ...: df['relative_months'] = df['Date1'].apply(lambda end: relative_months(start, end, freq = "M"))
     ...: 
25.7 s ± 729 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [110]: %%timeit
     ...: rd = df['Date1'].apply(lambda x:relativedelta(x,date(2019,1,1)))
     ...: mon = rd.apply(lambda x: ((x.years * 12) + x.months))
     ...: df['Diff'] = mon
     ...: 
94.2 ms ± 431 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    

Другие вопросы по теме