如何计算不同pandas列中两个日期之间的年数

时间:2018-06-12 11:47:38

标签: python pandas datetime dataframe

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

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:系列的真值是不明确的。使用a.empty,a.bool(),a.item(),a.any()或a.all()。

我不明白我的数据的模糊性,以及应用那些空/ bool / item的位置...... 对象数据类型的df['dta']列而不是日期时间,但在pd.to_datetime中包装dob的创建不会有帮助。

EDIT 预期的输出应该是

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

3 个答案:

答案 0 :(得分:3)

我认为需要:

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

当 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)