【问题标题】:How to calculate number of years between two dates in different pandas columns如何计算不同熊猫列中两个日期之间的年数
【发布时间】:2018-11-21 19:22:15
【问题描述】:

一列有日期,而另一列有一个包含日期的字符串,所以我首先需要从该字符串中提取日期部分。

import pandas as pd
import datetime
from dateutil.relativedelta import relativedelta

# the dataframe - id column always starts with year, month and day
df = pd.DataFrame({'id': ['19520630F8', '19680321A5', '19711113E2'],
                   'dte': ['2010-06-02', '2007-08-12', '2013-01-23']})

# create a date string from df['id'] to the format yyyy-mm-dd
dob = (df['id'].str[:4] + '-' +
       df['id'].str[4:6] + '-' +
       df['id'].str[6:8])

# calculate age (years only) at df['dte']
df['age'] = relativedelta(date, dob).years

我收到错误消息:

ValueError:Series 的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()。

我不明白我的数据的模糊性,以及在哪里应用这些空/布尔/项目... df['dta'] 列如果是对象数据类型而不是日期时间,但将 dob 的创建包装在 pd.to_datetime 中将无济于事。

编辑 预期的输出应该是

          dte          id  age
0  2010-06-02  19520630F8   57
1  2007-08-12  19680321A5   39
2  2013-01-23  19711113E2   41

【问题讨论】:

    标签: python pandas datetime dataframe


    【解决方案1】:

    我认为需要:

    df['age'] = (np.floor((pd.to_datetime(df['dte']) - 
                 pd.to_datetime(dob)).dt.days / 365.25)).astype(int)
    print (df)
               id         dte  age
    0  19520630F8  2010-06-02   57
    1  19680321A5  2007-08-12   39
    2  19711113E2  2013-01-23   41
    

    详情

    将列转换为日期时间并减去:

    print (pd.to_datetime(df['dte']) -  pd.to_datetime(dob))
    0   21156 days
    1   14388 days
    2   15047 days
    dtype: timedelta64[ns]
    

    转换为天,然后转换为年:

    print ((pd.to_datetime(df['dte']) -  pd.to_datetime(dob)).dt.days / 365.25)
    0    57.921971
    1    39.392197
    2    41.196441
    dtype: float64
    

    numpy.floor. 的最后一个 floor 值:

    print ((np.floor((pd.to_datetime(df['dte']) - pd.to_datetime(dob)).dt.days / 365.25)))
    0    57.0
    1    39.0
    2    41.0
    dtype: float64
    

    【讨论】:

    • 非常感谢!那行得通,但我意识到我需要真实的年龄,而不仅仅是年龄之间的差异
    • @leofer - 根据您的预期输出更改解决方案。
    【解决方案2】:

    这是使用dateutil.relativedelta 和列表理解的一种解决方案。重要的一点是确保在计算中使用它们之前有两个 datetime 系列。

    from dateutil.relativedelta import relativedelta
    
    df['id_dte'] = pd.to_datetime(df['id'].str[:8], format='%Y%m%d')
    df['dte'] = pd.to_datetime(df['dte'])
    
    df['age'] = [relativedelta(a, b).years for a, b in zip(df['dte'], df['id_dte'])]
    
    print(df)
    
             dte          id     id_dte  age
    0 2010-06-02  19520630F8 1952-06-30   57
    1 2007-08-12  19680321A5 1968-03-21   39
    2 2013-01-23  19711113E2 1971-11-13   41
    

    但是,如果您只想获取年份之间的差异(不是源自年龄),则可以直接使用datetime属性:

    df['age'] = df['dte'].dt.year - df['id_dte'].dt.year
    
    print(df)
    
             dte          id     id_dte  age
    0 2010-06-02  19520630F8 1952-06-30   58
    1 2007-08-12  19680321A5 1968-03-21   39
    2 2013-01-23  19711113E2 1971-11-13   42
    

    【讨论】:

    • 很好,谢谢!但是为什么要创建一个新列 df['id_dte']? df['id'] = pd.to_datetime(df['id'].str[:8], format='%Y%m%d') 似乎有效。
    • @leofer,因为您可能想稍后使用它,并且为了清楚起见。你可以完全省略它,比如df['age'] = df['dte'].dt.year - pd.to_datetime(df['id'].str[:8], format='%Y%m%d').dt.year。但这是一个难以理解的混乱。
    【解决方案3】:

    当 dte 和 id 具有相同的月/日时,除以 365.25 会出现问题。

    解决方案是减去年份,然后如果 dte 的月/日小于 id 的月/日,则从结果中减去 1。

    df['age'] = df['dte'].dt.year - df['id_dte'].dt.year
    
    df['age'] -= ((df['dte'].dt.month * 32 + df['dte'].dt.day) - (df['id_dte'].dt.month * 32 + df['id_dte'].dt.day)).apply(lambda x: 1 if x < 0 else 0)
    

    【讨论】:

      猜你喜欢
      • 2018-03-04
      • 2012-01-06
      • 2017-06-16
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 2012-12-13
      • 1970-01-01
      相关资源
      最近更新 更多