在新的pandas数据帧列中计算年,月等的日期时间差异

时间:2015-07-18 11:45:33

标签: python datetime pandas timedelta

我有一个像这样的pandas数据框:

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

我想添加一个新列,在年,月,日之间提供startend列之间的差异。

所以结果应该是这样的:

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

diff列也可能是datetime个对象或timedelta个对象,但关键是我可以轻松获得 Year

我到现在为止尝试的是:

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

这会导致新列包含10848 days。但是,我不知道如何将日期转换为 29y9m等。

7 个答案:

答案 0 :(得分:9)

使用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)

答案 1 :(得分:8)

您可以尝试用这种方式用年创建新列:

reader

答案 2 :(得分:7)

我认为这是最“大熊猫”的方式,不使用任何for循环或定义外部函数:

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

由于pandas的timedelda64不允许使用map而不是apply,因为它不允许对datetime对象进行简单的添加。

答案 3 :(得分:6)

通过简单的功能,您就可以实现目标。

该函数通过简单的计算计算年份差异和月份差异。

native_to_int64

答案 4 :(得分:4)

更简单的方法是使用date_range函数并计算相同的长度

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

答案 5 :(得分:0)

您可以尝试以下功能来计算差异 -

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)

其中row是数据框row。我假设您的startend列是datetime个对象。然后,您可以使用DataFrame.apply()函数将其应用于每一行。

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

答案 6 :(得分:0)

与@ DeepSpace的回答类似,这里有类似SAS的实现:

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

用法:

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