以小时和分钟为单位计算两个Pandas柱之间的时间差

qmelpv7a  于 2023-02-17  发布在  其他
关注(0)|答案(4)|浏览(179)

我在一个 Dataframe 中有两列,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列,但是当超过24小时时,它包含days

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

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

vawmfj5a

vawmfj5a1#

Pandas时间戳差异返回一个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
icnyk63a

icnyk63a2#

这让我抓狂,因为上面的.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()来处理跨越多天的时间段。

kg7wmglp

kg7wmglp3#

    • 如何将结果仅转换为小时和分钟 *
  • 接受的答案仅返回days + hours不包括分钟数。
  • 若要提供小时和分钟为hh:mmx hours y minutes的列,则需要进行额外的计算和设置字符串格式。
  • 下面的答案说明了如何使用timedelta数学方法将总小时数或总分钟数作为浮点数,这比使用.astype('timedelta64[h]')要快。
  • Pandas时间增量用户指南
  • Pandas Time series / date functionality User Guide
  • 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

其他方法

  • Other Resources中的播客中有一条值得注意的内容,.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

其他资源

测试

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

ma8fv8wu4#

默认情况下,Pandas时差的分辨率为纳秒,即timedelta64[ns],因此将其转换为秒/分钟/小时等的一种方法是将其纳秒表示除以10**9以转换为秒,除以60*10**9以转换为分钟等。此方法比本页建议的其他方法至少快3倍。1

df['diff_in_seconds'] = df['from_date'].sub(df['to_date']).view('int64') // 10**9
df['diff_in_minutes'] = df['from_date'].sub(df['to_date']).view('int64') // (60*10**9)
df['diff_in_hours'] = df['from_date'].sub(df['to_date']).view('int64') // (3600*10**9)

PS:上面的代码假设你想要的是整秒,整分钟,整小时的差值,所以它使用整数除法(//),但是如果你也想要分数,那么使用真除法(/)。也就是说,如果你想要精确的差值,那么考虑将差值转换为更高的分辨率(毫秒/微秒/等等),而不是分数秒/分钟/小时。
1一些使用Trenton McKinney's setup的基准测试:

data = {'to_date': [pd.Timestamp('2014-01-24 13:03:12.050000'), pd.Timestamp('2014-01-27 11:57:18.240000')]*1000000, 
        'from_date': [pd.Timestamp('2014-01-26 23:41:21.870000'), pd.Timestamp('2014-01-27 15:38:22.540000')]*1000000}
df = pd.DataFrame(data)
df['Diff'] = df['from_date'] - df['to_date']

%timeit df['Diff'].view('int64') // (3600*10**9)
# 11 ms ± 271 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df['Diff'] // pd.Timedelta(hours=1)
# 36.7 ms ± 2.99 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df['Diff'].astype('timedelta64[h]')
# 46.5 ms ± 865 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df['Diff'].dt.total_seconds() // 3600
# 169 ms ± 7.71 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)

相关问题