2015-07-18 30 views
12

Tôi có một dataframe gấu trúc nhìn như thế này:tính datetime-sự khác biệt trong những năm, tháng, vv trong một gấu trúc dataframe mới cột

Name start  end 
A  2000-01-10 1970-04-29 

Tôi muốn thêm một cột mới, tạo sự khác biệt giữa các startend cột trong năm, tháng, ngày.

Vì vậy, kết quả sẽ giống như thế:

Name start  end   diff 
A  2000-01-10 1970-04-29 29y9m etc. 

cột khác cũng có thể là một đối tượng datetime hoặc một đối tượng timedelta, nhưng điểm quan trọng đối với tôi là, tôi có thể dễ dàng nhận được các NămTháng trong số đó.

gì tôi đã cố gắng cho đến bây giờ là:

df['diff'] = df['end'] - df['start'] 

Điều này dẫn đến cột mới chứa 10848 days. Tuy nhiên, tôi không biết cách chuyển đổi ngày thành 29y9m, v.v.

Trả lời

6

Với chức năng đơn giản, bạn có thể đạt được mục tiêu của mình.

Hàm này tính chênh lệch năm và chênh lệch tháng với phép tính đơn giản.

import pandas as pd 
import datetime 

def parse_date(td): 
    resYear = float(td.days)/364.0     # get the number of years including the the numbers after the dot 
    resMonth = int((resYear - int(resYear))*364/30) # get the number of months, by multiply the number after the dot by 364 and divide by 30. 
    resYear = int(resYear) 
    return str(resYear) + "Y" + str(resMonth) + "m" 

df = pd.DataFrame([("2000-01-10", "1970-04-29")], columns=["start", "end"]) 
df["delta"] = [parse_date(datetime.datetime.strptime(start, '%Y-%m-%d') - datetime.datetime.strptime(end, '%Y-%m-%d')) for start, end in zip(df["start"], df["end"])] 
print df 

     start   end delta 
0 2000-01-10 1970-04-29 29Y9m 
7

Khá nhiều đơn giản với relativedelta:

from dateutil import relativedelta 

>>   end  start 
>> 0 1970-04-29 2000-01-10 

for i in df.index: 
    df.at[i, 'diff'] = relativedelta.relativedelta(df.ix[i, 'start'], df.ix[i, 'end']) 

>>   end  start           diff 
>> 0 1970-04-29 2000-01-10 relativedelta(years=+29, months=+8, days=+12) 
0

Bạn có thể thử các chức năng sau đây để tính toán sự khác biệt -

def yearmonthdiff(row): 
    s = row['start'] 
    e = row['end'] 
    y = s.year - e.year 
    m = s.month - e.month 
    d = s.day - e.day 
    if m < 0: 
     y = y - 1 
     m = m + 12 
    if m == 0: 
     if d < 0: 
      m = m -1 
     elif d == 0: 
      s1 = s.hour*3600 + s.minute*60 + s.second 
      s2 = e.hour*3600 + e.minut*60 + e.second 
      if s1 < s2: 
       m = m - 1 
    return '{}y{}m'.format(y,m) 

đâu hàng là dataframe row. Tôi giả sử các cột startend của bạn là datetime đối tượng. Sau đó, bạn có thể sử dụng chức năng DataFrame.apply() để áp dụng nó cho mỗi hàng.

df 

Out[92]: 
         start      end 
0 2000-01-10 00:00:00.000000 1970-04-29 00:00:00.000000 
1 2015-07-18 17:54:59.070381 2014-01-11 17:55:10.053381 

df['diff'] = df.apply(yearmonthdiff, axis=1) 

In [97]: df 
Out[97]: 
         start      end diff 
0 2000-01-10 00:00:00.000000 1970-04-29 00:00:00.000000 29y9m 
1 2015-07-18 17:54:59.070381 2014-01-11 17:55:10.053381 1y6m 
+0

'" Tôi không thể nghĩ ra bất kỳ chức năng trực tiếp nào cung cấp cho sự khác biệt erence trong năm và tháng "' Xem 'relativedelta' trong câu trả lời của tôi – DeepSpace

7

Tôi nghĩ rằng đây là 'gấu trúc' nhất cách để làm điều đó, mà không sử dụng bất kỳ cho vòng lặp hoặc quy định chức năng bên ngoài:

>>> df = pd.DataFrame({'Name': ['A'], 'start': [datetime(2000, 1, 10)], 'end': [datetime(1970, 4, 29)]}) 
>>> df['diff'] = map(lambda td: datetime(1, 1, 1) + td, list(df['start'] - df['end'])) 
>>> df['diff'] = df['diff'].apply(lambda d: '{0}y{1}m'.format(d.year - 1, d.month - 1)) 
>>> df 
    Name  end  start diff 
0 A 1970-04-29 2000-01-10 29y8m 

Đã phải sử dụng bản đồ thay vì áp dụng vì timedelda64 gấu trúc , không cho phép bổ sung đơn giản vào đối tượng datetime.

0

Tương tự như câu trả lời @ DeepSpace của, đây là một thực hiện SAS như:

import pandas as pd 
from dateutil import relativedelta 

def intck_month(start, end): 
    rd = relativedelta.relativedelta(pd.to_datetime(end), pd.to_datetime(start)) 
    return rd.years, rd.months 

Cách sử dụng:

>> years, months = intck_month('1960-01-01', '1970-03-01') 
>> print(years) 
10 
>> print(months) 
2 
2

Một cách đơn giản hơn nhiều là sử dụng DATE_RANGE chức năng và tính toán chiều dài của cùng một

startdt=pd.to_datetime('2017-01-01') enddt = pd.to_datetime('2018-01-01') len(pd.date_range(start=startdt,end=enddt,freq='M'))

+0

Đây thực sự là giải pháp đơn giản nếu bạn đã làm việc với gấu trúc trong dự án. –

Các vấn đề liên quan