计算两列之间的Pandas DataFrame时间差异(以小时和分钟为单位)


85

我在数据框中有两列fromdatetodate

import pandas as pd

data = {'todate': [pd.Timestamp('2014-01-24 13:03:12.050000'), pd.Timestamp('2014-01-27 11:57:18.240000'), pd.Timestamp('2014-01-23 10:07:47.660000')],
        'fromdate': [pd.Timestamp('2014-01-26 23:41:21.870000'), pd.Timestamp('2014-01-27 15:38:22.540000'), pd.Timestamp('2014-01-23 18:50:41.420000')]}

df = pd.DataFrame(data)

我添加了一个新列,diff以使用找出两个日期之间的差异

df['diff'] = df['fromdate'] - df['todate']

我得到了该diff列,但是days当超过24小时时,它包含。

                   todate                fromdate                   diff
0 2014-01-24 13:03:12.050 2014-01-26 23:41:21.870 2 days 10:38:09.820000
1 2014-01-27 11:57:18.240 2014-01-27 15:38:22.540 0 days 03:41:04.300000
2 2014-01-23 10:07:47.660 2014-01-23 18:50:41.420 0 days 08:42:53.760000

如何将结果仅转换为小时和分钟(即,将天转换为小时)?

Answers:


123

熊猫的时间戳差异返回datetime.timedelta对象。可以使用* as_type *方法将其轻松转换为小时,就像这样

import pandas
df = pandas.DataFrame(columns=['to','fr','ans'])
df.to = [pandas.Timestamp('2014-01-24 13:03:12.050000'), pandas.Timestamp('2014-01-27 11:57:18.240000'), pandas.Timestamp('2014-01-23 10:07:47.660000')]
df.fr = [pandas.Timestamp('2014-01-26 23:41:21.870000'), pandas.Timestamp('2014-01-27 15:38:22.540000'), pandas.Timestamp('2014-01-23 18:50:41.420000')]
(df.fr-df.to).astype('timedelta64[h]')

产生

0    58
1     3
2     8
dtype: float64

astype解决方法可以工作,但是对于大型文件(0.5百万行)而言,它太慢了。还有其他建议吗?
学生1年1

3
timedelta对象具有日期和秒的属性...,您可以这样做(df.fr-df.to).dt.days * 24 +(df.fr-df.to).dt.seconds / 3600
nitin

1
谢谢!这对我来说也可以用来计算年数(以获得年龄):df ['age'] =(df ['later_date']-df ['birth_date'])。astype('timedelta64 [Y]')
Superduper

47

因为.astype()上面的解决方案对我不起作用,所以这使我发疯。但是我找到了另一种方式。尚未计时或任何计时,但可能对其他人有用:

t1 = pd.to_datetime('1/1/2015 01:00')
t2 = pd.to_datetime('1/1/2015 03:30')

print pd.Timedelta(t2 - t1).seconds / 3600.0

...如果你想要几个小时。要么:

print pd.Timedelta(t2 - t1).seconds / 60.0

...如果你想几分钟。


9
我遇到了同样的问题,但是在您的解决方案中,您需要小心,因为会忽略大于一天的时差,并且需要将其单独包括在内
马蹄铁

39
我只是发现这.total_seconds()对需要的人
马蹄铁

奇怪的是(我注意到4年后),您必须使用parens ().total_seconds()但不能使用.seconds
elPastor

5
  • 如何将结果转换为仅数小时和数分钟
    • 接受的答案只会返回days + hours分钟不包括在内。
  • 要提供具有小时和分钟(如hh:mm或)的列x hours y minutes,将需要其他计算和字符串格式。
  • 该答案显示了如何使用timedelta数学运算来获取总小时数或总分钟数,并且比使用数学方法更快.astype('timedelta64[h]')
  • 熊猫时间增量用户指南
  • 熊猫时间序列/日期功能用户指南
  • pythontimedelta对象:请参阅支持的操作。
import pandas as pd

# test data from OP, with values already in a datetime format
data = {'to_date': [pd.Timestamp('2014-01-24 13:03:12.050000'), pd.Timestamp('2014-01-27 11:57:18.240000'), pd.Timestamp('2014-01-23 10:07:47.660000')],
        'from_date': [pd.Timestamp('2014-01-26 23:41:21.870000'), pd.Timestamp('2014-01-27 15:38:22.540000'), pd.Timestamp('2014-01-23 18:50:41.420000')]}

# test dataframe; the columns must be in a datetime format; use pandas.to_datetime if needed
df = pd.DataFrame(data)

# add a timedelta column if wanted. It's added here for information only
# df['time_delta_with_sub'] = df.from_date.sub(df.to_date)  # also works
df['time_delta'] = (df.from_date - df.to_date)

# create a column with timedelta as total hours, as a float type
df['tot_hour_diff'] = (df.from_date - df.to_date) / pd.Timedelta(hours=1)

# create a colume with timedelta as total minutes, as a float type
df['tot_mins_diff'] = (df.from_date - df.to_date) / pd.Timedelta(minutes=1)

# display(df)
                  to_date               from_date             time_delta  tot_hour_diff  tot_mins_diff
0 2014-01-24 13:03:12.050 2014-01-26 23:41:21.870 2 days 10:38:09.820000      58.636061    3518.163667
1 2014-01-27 11:57:18.240 2014-01-27 15:38:22.540 0 days 03:41:04.300000       3.684528     221.071667
2 2014-01-23 10:07:47.660 2014-01-23 18:50:41.420 0 days 08:42:53.760000       8.714933     522.896000

其他方法

  • .total_seconds()核心开发人员休假时添加并合并了来自其他资源中的播客中的一项注释,并且不会被批准。
    • 这也是为什么没有其他.total_xx方法的原因。
# convert the entire timedelta to seconds
# this is the same as td / timedelta(seconds=1)
(df.from_date - df.to_date).dt.total_seconds()
[out]:
0    211089.82
1     13264.30
2     31373.76
dtype: float64

# get the number of days
(df.from_date - df.to_date).dt.days
[out]:
0    2
1    0
2    0
dtype: int64

# get the seconds for hours + minutes + seconds, but not days
# note the difference from total_seconds
(df.from_date - df.to_date).dt.seconds
[out]:
0    38289
1    13264
2    31373
dtype: int64

其他资源

%%timeit 测试

import pandas as pd

# dataframe with 2M rows
data = {'to_date': [pd.Timestamp('2014-01-24 13:03:12.050000'), pd.Timestamp('2014-01-27 11:57:18.240000')], 'from_date': [pd.Timestamp('2014-01-26 23:41:21.870000'), pd.Timestamp('2014-01-27 15:38:22.540000')]}
df = pd.DataFrame(data)
df = pd.concat([df] * 1000000).reset_index(drop=True)

%%timeit
(df.from_date - df.to_date) / pd.Timedelta(hours=1)
[out]:
43.1 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
(df.from_date - df.to_date).astype('timedelta64[h]')
[out]:
59.8 ms ± 1.29 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.