【问题标题】:Don't take leap years into account when adding months to date in Pandas在 Pandas 中添加迄今为止的月份时不要考虑闰年
【发布时间】:2021-08-04 20:46:52
【问题描述】:

我需要执行以下操作。我的数据框中有一个日期列,我需要像这样添加 x 个月:

df = pd.DataFrame({'date':['2019-01-01', '2018-01-01']})
df['date'] = pd.to_datetime(df['date']).dt.date
months = 24
df['date'] = df['date'] + np.timedelta64(months, 'M')

问题是我不想考虑闰年,所以第一次日期的结果是“2021-01-01”而不是“2020-12-31”。 (2020 年是闰年。)另一个日期很好。

有没有简单的解决方案?目前还没有找到。

谢谢。

【问题讨论】:

  • 如果你得到了 2020-11-20。你期待什么输出
  • @RinshanKolayil 2022-11-20

标签: python pandas


【解决方案1】:
import pandas as pd
import datetime
import numpy as np

df = pd.DataFrame({'date':['2019-01-01', '2018-01-01']})
df['date'] = pd.to_datetime(df['date'])

months=24

if df['date'].dt.is_leap_year.any() == False:
    df['date'] = df['date'] + np.timedelta64(months, 'M')
else:
    df['date'] = df['date'] + np.timedelta64(months, 'M') - np.timedelta64(df['date'].dt.is_leap_year.sum(), 'D')

【讨论】:

  • 编辑了我的问题,我需要一个通用的解决方案,以便在有闰年和没有闰年时都可以使用它。不过谢谢。
  • @JanValušek 试试这个,它应该做你想做的事,第一步是检查闰年,第二步将计算闰年,如果有的话,减去闰年
  • @JanValušek 我刚刚修改了代码以使用 np.timedelta64,请检查一下,让我知道它是否符合您的要求,我已经尝试了一些测试用例,它似乎工作
  • @JanValušek 我的方法是否达到了您的要求?
【解决方案2】:
import pandas as pd
import numpy as np
from datetime import datetime
def add_date(date):
    d = date + np.timedelta64(months, 'M')
    y = d.year
    if d.is_leap_year:
        y = y + 1 # Here you can add more conditions
        return datetime(year=y, month=1, day=1)
        #or return d + pd.offsets.DateOffset(years=1)
    return datetime(year=y, month=d.month, day=d.day) #or d
df = pd.DataFrame({'date':['2019-01-03', '2018-01-01','2018-11-21','2017-05-01']})
months = 24
df['date'] = pd.to_datetime(df['date']).apply(add_date)
print(df)
# Or you can use by dayofyear attribute provide by pandas
def add_date(date):
    d = date + np.timedelta64(months, 'M')
    days = 0
    if d.is_leap_year:
        days = 367 - d.day_of_year
    return date + np.timedelta64(months, 'M') + np.timedelta64(days, 'D')

输出

       date
0 2021-01-02 #d = 2021-01-02 11:38:24 - Not leap year
1 2021-01-01 #d = 2020-01-01 11:38:24 - Leap year
2 2021-01-01 #d = 2020-11-20 11:38:24 - Leap year
3 2019-05-01 #d = 2019-05-01 11:38:24 - Not leap year
# where d=date+ np.timedelta64(24, 'M')

如果您想检查数据框中的日期,您可以执行以下操作,

def add_date(date):
    days = 0
    if date.is_leap_year :
        days = 367 - date.day_of_year
    return date + np.timedelta64(months, 'M') + np.timedelta64(days, 'D')

【讨论】:

    【解决方案3】:
    df['date'] = df['date'] + pd.offsets.DateOffset(years=2)
    

    类似于:How to add a year to a column of dates in pandas

    限制自己仅添加小于 12 的月份。闰年是“年”的概念。像 np.timedelta() 这样的函数永远无法得到它;这是设计使然。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      • 2019-07-14
      • 2019-04-05
      • 2015-06-21
      • 1970-01-01
      • 2017-05-25
      相关资源
      最近更新 更多