【问题标题】:Elegant way to add years as timedelta units to shift dates - Pandas将年份作为 timedelta 单位添加以更改日期的优雅方式 - Pandas
【发布时间】:2020-06-25 04:28:05
【问题描述】:

我有一个如下所示的数据框

df1 = pd.DataFrame({'person_id': [11,11,11,21,21],
                        'admit_dates': ['03/21/2015', '01/21/2016', '7/20/2018','01/11/2017','12/31/2011'],
                        'discharge_dates': ['05/09/2015', '01/29/2016', '7/27/2018','01/12/2017','01/31/2016'],
                        'drug_start_dates': ['05/29/1967', '01/21/1957', '7/27/1959','01/01/1961','12/31/1961'],
                        'offset':[223,223,223,310,310]})

我想做的是将offset 中的years 添加到日期列中。

所以,我试图用unit=yunit=Y 将偏移量转换为timedelta 对象,然后转移admit_dates

df1['offset'] = pd.to_timedelta(df1['offset'],unit='Y') #also tried with `y` (small y)
df1['shifted_date'] = df1['admit_dates'] + df1['offset']

但是,我收到以下错误

ValueError:不再支持单位“M”和“Y”,因为它们不支持 表示明确的 timedelta 值持续时间。

还有其他优雅的方法可以将日期按years 移动吗?

【问题讨论】:

  • 年份偏移的问题是您最终可能会得到无效的日期,例如当将 02/29/2020 偏移 3 年时。

标签: python pandas dataframe python-datetime timedelta


【解决方案1】:

pandas 支持的最大TimestampTimestamp('2262-04-11 23:47:16.854775807'),因此您无法添加310 迄今为止的年份12/31/2011,一种可能的方法是使用python 的日期时间对象,它支持最大年份达到@987654325 @ 所以你应该可以添加 310 年。

from dateutil.relativedelta import relativedelta

df['admit_dates'] = pd.to_datetime(df['admit_dates'])
df['admit_dates'] = df['admit_dates'].dt.date.add(
    df['offset'].apply(lambda y: relativedelta(years=y)))

结果:

df
   person_id admit_dates discharge_dates drug_start_dates  offset
0         11  2238-03-21      05/09/2015       05/29/1967     223
1         11  2239-01-21      01/29/2016       01/21/1957     223
2         11  2241-07-20       7/27/2018        7/27/1959     223
3         21  2327-01-11      01/12/2017       01/01/1961     310
4         21  2321-12-31      01/31/2016       12/31/1961     310

【讨论】:

  • @TheGreat Sure,让我检查一下。
  • @TheGreat,添加了答案。
【解决方案2】:

您可以做的一件事是从日期中提取年份,并将其添加到偏移量中:

df1 = pd.DataFrame({'person_id': [11,11,11,21,21],
                        'admit_dates': ['03/21/2015', '01/21/2016', '7/20/2018','01/11/2017','12/31/2011'],
                        'discharge_dates': ['05/09/2015', '01/29/2016', '7/27/2018','01/12/2017','01/31/2016'],
                        'drug_start_dates': ['05/29/1967', '01/21/1957', '7/27/1959','01/01/1961','12/31/1961'],
                        'offset':[10,20,2,31,12]})
df1.admit_dates = pd.to_datetime(df1.admit_dates)

df1["new_year"] = df1.admit_dates.dt.year + df1.offset
df1["date_with_offset"] = pd.to_datetime(pd.DataFrame({"year": df1.new_year, 
                                                  "month": df1.admit_dates.dt.month, 
                                                  "day":df1.admit_dates.dt.day}))

问题 - 使用您的原始偏移量,某些日期会导致以下错误:

OutOfBoundsDatetime: Out of bounds nanosecond timestamp: 2328-01-11 00:00:00

根据the documentation,pandas 中的最大日期是 2262 年 4 月 11 日(具体时间大约是 15 点到午夜)。这可能是因为它们以纳秒为单位保持时间,这就是这种表示发生越界错误的时候。

【讨论】:

  • 感谢您的回复。赞成。但我可以知道为什么它会抛出outofbounds 错误,因为2328-01-11 是一个有效日期(是的,308 年后)。 pandas 允许的年限是多少?
  • 查看我的编辑。如果这回答了您的问题,您也可以为后代接受它(单击问题旁边的复选标记)。
【解决方案3】:

单位 'Y' 和 'M' 自 pandas 0.25.0 起已弃用 但是感谢 numpy timedelta64,通过它我们可以在 pandas Timedelta 中使用这些单位

import pandas as pd
import numpy as np

# Builds your dataframe
df1 = pd.DataFrame({'person_id': [11,11,11,21,21],
                    'admit_dates': ['03/21/2015', '01/21/2016', '7/20/2018','01/11/2017','12/31/2011'],
                    'discharge_dates': ['05/09/2015', '01/29/2016', '7/27/2018','01/12/2017','01/31/2016'],
                    'drug_start_dates': ['05/29/1967', '01/21/1957', '7/27/1959','01/01/1961','12/31/1961'],
                    'offset':[223,223,223,310,310]})

>>> df1
   person_id admit_dates discharge_dates drug_start_dates  offset
0         11  03/21/2015      05/09/2015       05/29/1967     223
1         11  01/21/2016      01/29/2016       01/21/1957     223
2         11   7/20/2018       7/27/2018        7/27/1959     223
3         21  01/11/2017      01/12/2017       01/01/1961     310
4         21  12/31/2011      01/31/2016       12/31/1961     310

>>> df1['shifted_date'] = df1.apply(lambda r: pd.Timedelta(np.timedelta64(r['offset'], 'Y'))+ pd.to_datetime(r['admit_dates']), axis=1)
>>> df1['shifted_date'] = df1['shifted_date'].dt.date
>>> df1
   person_id admit_dates discharge_dates drug_start_dates  offset shifted_date
0         11  03/21/2015      05/09/2015       05/29/1967     223   2238-03-21
1         11  01/21/2016      01/29/2016       01/21/1957     223   2239-01-21
2         11   7/20/2018       7/27/2018        7/27/1959     223   2241-07-20
....

【讨论】:

    猜你喜欢
    • 2012-09-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 2017-04-16
    相关资源
    最近更新 更多