Pandas Timedelta в месяцах

Как я могу вычислить прошедшие месяцы с помощью pandas? Я пишу следующее, но этот код не изящный. Не могли бы вы сказать мне лучший способ?

import pandas as pd

df = pd.DataFrame([pd.Timestamp('20161011'),
                   pd.Timestamp('20161101') ], columns=['date'])
df['today'] = pd.Timestamp('20161202')

df = df.assign(
    elapsed_months=(12 *
                    (df["today"].map(lambda x: x.year) -
                     df["date"].map(lambda x: x.year)) +
                    (df["today"].map(lambda x: x.month) -
                     df["date"].map(lambda x: x.month))))
# Out[34]: 
#         date      today  elapsed_months
# 0 2016-10-11 2016-12-02               2
# 1 2016-11-01 2016-12-02               1

Ответ 1

Обновление для панд 0.24.0:

Поскольку версия 0.24.0 изменила API для возврата объекта MonthEnd из вычитания периода, вы можете выполнить некоторые ручные вычисления следующим образом, чтобы получить разницу за весь месяц:

12 * (df.today.dt.year - df.date.dt.year) + (df.today.dt.month - df.date.dt.month)

# 0    2
# 1    1
# dtype: int64

Завернуть в функцию:

def month_diff(a, b):
    return 12 * (a.dt.year - b.dt.year) + (a.dt.month - b.dt.month)

month_diff(df.today, df.date)
# 0    2
# 1    1
# dtype: int64

До панды 0.24.0. Вы можете округлить дату до месяца с помощью to_period() а затем вычесть результат:

df['elapased_months'] = df.today.dt.to_period('M') - df.date.dt.to_period('M')

df
#         date       today  elapased_months
#0  2016-10-11  2016-12-02                2
#1  2016-11-01  2016-12-02                1

Ответ 2

вы также можете попробовать:

df['months'] = (df['today'] - df['date']) / np.timedelta64(1, 'M')
df
#      date      today    months
#0 2016-10-11 2016-12-02  1.708454
#1 2016-11-01 2016-12-02  1.018501

Ответ 3

Следующее выполнит следующее:

df["elapsed_months"] = ((df["today"] - df["date"]).
                        map(lambda x: round(x.days/30)))


# Out[34]: 
#         date      today  elapsed_months
# 0 2016-10-11 2016-12-02               2
# 1 2016-11-01 2016-12-02               1