如何在Pandas中转换timedelta格式并实现按用户分区累计求和
我来帮你一步步解决这三个问题,先看修改后的完整代码,再逐个解释细节:
import pandas as pd import datetime import numpy as np from datetime import timedelta dfMockLog = [ (1, ("2017-01-01 09:00:00"), "htt://x.org/page1.html"), (1, ("2017-01-01 09:01:00"), "htt://x.org/page2.html"), (1, ("2017-01-01 09:02:00"), "htt://x.org/page3.html"), (1, ("2017-01-01 09:05:00"), "htt://x.org/page3.html"), (1, ("2017-01-01 09:30:00"), "htt://x.org/page2.html"), (1, ("2017-01-01 09:33:00"), "htt://x.org/page1.html"), (1, ("2017-01-01 09:37:00"), "htt://x.org/page2.html"), (1, ("2017-01-01 09:41:00"), "htt://x.org/page3.html"), (1, ("2017-01-01 10:00:00"), "htt://x.org/page1.html"), (1, ("2017-01-01 11:00:00"), "htt://x.org/page2.html"), (2, ("2017-01-01 09:41:00"), "htt://x.org/page3.html"), (2, ("2017-01-01 09:42:00"), "htt://x.org/page1.html"), (2, ("2017-01-01 09:43:00"), "htt://x.org/page2.html") ] dfMockLog = pd.DataFrame(dfMockLog, columns=['user', 'Timestamp', 'url']) dfMockLog['Timestamp'] = pd.to_datetime(dfMockLog['Timestamp']) dfMockLog = dfMockLog.sort_values(['user','Timestamp']) dfMockLog['previous_end'] = dfMockLog.groupby(['user'])['Timestamp'].shift(1) # 需求1:将time_diff转换为秒数格式 dfMockLog['time_diff'] = dfMockLog['Timestamp'] - dfMockLog['previous_end'] # 简化计算,无需apply dfMockLog['time_diff_seconds'] = dfMockLog['time_diff'].dt.total_seconds() # 转为总秒数 # 需求2:按user字段分区累计求和(提供两种格式选择) dfMockLog['cum_sum_seconds'] = dfMockLog.groupby('user')['time_diff_seconds'].cumsum() dfMockLog['cum_sum_timedelta'] = dfMockLog.groupby('user')['time_diff'].cumsum() print(dfMockLog)
1. 把"time_diff"转换为秒数格式
原代码用apply计算时间差可以简化,直接用列运算dfMockLog['Timestamp'] - dfMockLog['previous_end']就能得到timedelta类型的列。要转成秒数,用pandas内置的dt.total_seconds()方法最方便——它会自动把天、小时、分钟等所有时间分量转换成总秒数,比手动计算days*86400 + seconds高效得多。
2. 按user分区累计求和
要实现分组累计,只需要用groupby('user')指定分组字段,再对目标列调用cumsum()即可。这里提供了两种方案:
cum_sum_seconds:累计秒数,结果是数值类型,适合后续统计计算;cum_sum_timedelta:直接累计timedelta类型,保留时间差格式,适合需要直观展示时长的场景。
3. timedelta类型的可用格式/操作
不管是Python原生的datetime.timedelta还是pandas的Timedelta,都有这些常用的格式转换方式:
直接获取时间分量(属性)
.days:提取整数天数.seconds:提取小时、分钟、秒转换后的总秒数(范围0-86399).microseconds:提取微秒数(范围0-999999).nanoseconds:提取纳秒数(仅pandas Timedelta支持)
转换为总时长(方法)
.total_seconds():获取时间差的总秒数(含天、微秒等,返回浮点数).total_seconds() * 1000:转换为毫秒数.total_seconds() / 3600:转换为小时数.total_seconds() / 86400:转换为天数
格式化可读字符串
如果要输出成友好的文本格式,可以自己拼接:
td = timedelta(hours=2, minutes=30, seconds=15) print(f"{td.days}天 {td.seconds//3600}小时 {(td.seconds%3600)//60}分钟 {td.seconds%60}秒") # 输出:0天 2小时 30分钟 15秒
pandas的dt.strftime也支持部分格式符(比如%H:%M:%S),但对天数的支持有限,适合短时长的格式化:
dfMockLog['time_diff_str'] = dfMockLog['time_diff'].dt.strftime("%H:%M:%S")
内容的提问来源于stack exchange,提问作者CodeVY
相关产品推荐
相关产品推荐

