2014-11-06 83 views
4

我如何計算一個人的年齡(基於dob列)並添加一列到新數據框中?熊貓得到一個日期的年齡(例如:出生日期)

數據框如下所示:

lname  fname  dob 
0 DOE  LAURIE 03011979 
1 BOURNE JASON  06111978 
2 GRINCH XMAS  12131988 
3 DOE  JOHN  11121986 

我試着做以下幾點:

now = datetime.now() 
df1['age'] = now - df1['dob'] 

但是,收到以下錯誤:

類型錯誤:不支持的操作類型爲 - :'datetime.datetime'和'str'

回答

13
import datetime as DT 
import io 
import numpy as np 
import pandas as pd 

pd.options.mode.chained_assignment = 'warn' 

content = '''  ssno  lname   fname pos_title    ser gender dob 
0 23456789 PLILEY  JODY  BUDG ANAL    0560 F  031871 
1 987654321 NOEL  HEATHER  PRTG SRVCS SPECLST 1654 F  120852 
2 234567891 SONJU  LAURIE  SUPVY CONTR SPECLST 1102 F  010999 
3 345678912 MANNING CYNTHIA  SOC SCNTST   0101 F  081692 
4 456789123 NAUERTZ ELIZABETH OFF AUTOMATION ASST 0326 F  031387''' 

df = pd.read_table(io.BytesIO(content), sep='\s{2,}') 
df['dob'] = df['dob'].apply('{:06}'.format) 

now = pd.Timestamp(DT.datetime.now()) 
df['dob'] = pd.to_datetime(df['dob'], format='%m%d%y') # 1 
df['dob'] = df['dob'].where(df['dob'] < now, df['dob'] - np.timedelta64(100, 'Y')) # 2 
df['age'] = (now - df['dob']).astype('<m8[Y]') # 3 
print(df) 

產生

 ssno lname  fname   pos_title ser gender \ 
0 23456789 PLILEY  JODY   BUDG ANAL 560  F 
1 987654321  NOEL HEATHER PRTG SRVCS SPECLST 1654  F 
2 234567891 SONJU  LAURIE SUPVY CONTR SPECLST 1102  F 
3 345678912 MANNING CYNTHIA   SOC SCNTST 101  F 
4 456789123 NAUERTZ ELIZABETH OFF AUTOMATION ASST 326  F 

        dob age 
0 1971-03-18 00:00:00 43 
1 1952-12-08 18:00:00 61 
2 1999-01-09 00:00:00 15 
3 1992-08-16 00:00:00 22 
4 1987-03-13 00:00:00 27 

  1. 它看起來像你的dob列當前字符串。首先, 使用pd.to_datetime將它們轉換爲Timestamps
  2. 格式'%m%d%y'的最後兩位數字轉換爲多年,但不幸的是 假設52意味着2052因爲這可能不是 希瑟諾埃爾的birthyear,讓我們減去百年從dob 每當dobnow更大。您可能希望在條件df['dob'] < now減去幾年now,因爲它可能會稍微更可能有A 101歲的工人超過1歲的工人...
  3. 您可以從now減去dob獲得timedelta64[ns]。若要將 轉換爲年,請使用astype('<m8[Y]')astype('timedelta64[Y]')
+0

在.py文件中運行時,出現以上代碼中的以下錯誤。這是什麼意思 SettingWithCopyWarning:一個值試圖在DataFrame的一個切片副本上設置。 嘗試使用.loc [row_index,col_indexer] =值代替 df1 ['dob'] = pd.to_datetime(df1 ['dob'],format ='%m%d%y') c:\ users \ davidl 〜1 \ appdata \ local \ temp \ 1 \ tmpxt4mqz.py:37: 嘗試使用.loc [row_index,col_indexer] = value而不是 df1 ['dob'] = df1 ['dob']。其中(df1 [ dob'] david 2014-11-08 00:00:31

+0

該警告不是錯誤,但它是警告,代碼*可能*被分配給數據而不是DataFrame中的原始數據。見[這個答案](http://stackoverflow.com/a/21463854/190597)和[文檔](http://pandas.pydata.org/pandas-docs/dev/indexing.html#why-does-在-賦值時,使用鏈索引失效)。我認爲這是上述代碼中的虛驚,但我不確定爲什麼你會看到警告,因爲當我運行上面的代碼時,我看不到任何警告。當你運行上面的代碼時,你看到警告了嗎? – unutbu 2014-11-08 01:01:34

+0

對不起,我得到了上面代碼的ValueError。 – david 2014-11-08 17:12:20

2

首先想到的是,你的歲月是兩位數字,在這個時代這是一個不太好的選擇。無論如何,我要假設像05這樣的年份實際上是1905。這可能是不正確的(!),但提出正確的規則將取決於您的數據。

from datetime import date 

def age(date1, date2): 
    naive_yrs = date2.year - date1.year 
    if date1.replace(year=date2.year) > date2: 
     correction = -1 
    else: 
     correction = 0 
    return naive_yrs + correction 

df1['age'] = df1['dob'].map(lambda x: age(date(int('19' + x[-2:]), int(x[:2]), int(x[2:-2])), date.today())) 
+0

unutbu的答案一定會比我的答案快,因爲它使用了我沒有打擾學習的numpy日期磁貼。 – 2014-11-06 21:20:26