以小时和分钟为单位计算两列大熊猫之间的时差

在数据框架中有两列,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

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

359948 次浏览

熊猫时间戳差异返回一个 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()解决方案对我不起作用。但我找到了另一种方法。没有计时或者其他什么的,但是可能对其他人有用:

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

如果你想要几分钟的话。

更新: 这里曾经有一个很有帮助的评论,提到在多天的时间内使用 .total_seconds()。既然它不见了,我更新了答案。

  • 如何将结果仅转换为小时和分钟
    • 接受的答案只返回 days + hours.不包括会议记录。
  • 若要提供小时和分钟为 hh:mmx hours y minutes的列,则需要进行额外的计算和字符串格式设置。
  • 这个答案显示了如何使用 timedelta数学得到总小时或总分钟作为浮点数,并且比使用 .astype('timedelta64[h]')快。
  • 熊猫时间三角洲用户指南
  • 熊猫时间系列/日期功能用户指南
  • Python timedelta对象 : 查看支持的操作。
  • 下面的示例数据已经是 datetime64[ns] dtype。需要使用 pandas.to_datetime()转换所有相关列。
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)