如何将Pandas中含毫秒的分秒格式列转换为时间类型?
解决Pandas中「分钟:秒.毫秒」格式列的转换与时长计算问题
我来帮你搞定这个时间格式转换的问题!你遇到的ValueError是因为格式字符串没包含毫秒部分——你的数据里有.5这样的毫秒值,但你用的%M:%S只匹配了分钟和秒,漏掉了毫秒,所以才会提示有未转换的数据。
正确的转换方式:用timedelta类型处理时间间隔
因为你最终要做时间减法得到时长,最适合的类型是timedelta(时间间隔),而不是datetime.time(一天中的时刻)。time类型更适合表示具体几点几分,做减法的话如果出现跨周期(比如从58分跳到00分)会得到不符合预期的负数,而timedelta专门用来表示时间长度,完美适配你的需求。
具体代码实现
下面是针对你的数据的完整解决方案:
import pandas as pd # 你的示例数据 merged = pd.DataFrame({ 'started_at': ['58:42.5', '00:55.5'], 'ended_at': ['00:02.3', '02:13.9'] }) # 将列转换为timedelta类型,格式匹配「分钟:秒.毫秒」 merged['started_at'] = pd.to_timedelta(merged['started_at'], format='%M:%S.%f') merged['ended_at'] = pd.to_timedelta(merged['ended_at'], format='%M:%S.%f') # 计算时长(ended_at - started_at) merged['duration'] = merged['ended_at'] - merged['started_at'] # 可选:将时长转换为总秒数(方便后续数值运算,比如统计、绘图等) merged['duration_total_seconds'] = merged['duration'].dt.total_seconds() print(merged)
代码解释
- 格式字符串
%M:%S.%f:%M:匹配两位分钟数(比如58、00)%S:匹配两位秒数(比如42、55)%f:匹配微秒数(你的数据里的.5是500毫秒,pd.to_timedelta会自动识别为500000微秒)
timedelta的优势:- 直接支持减法运算,结果还是
timedelta类型,能直观看到时长(比如-0 days 00:56:40.200000) - 可以通过
dt.total_seconds()转换为浮点型的总秒数,方便后续的数值分析、排序等操作
- 直接支持减法运算,结果还是
- 注意事项:
- 如果你的业务场景中,
ended_at应该晚于started_at(比如第二个示例的00:55.5到02:13.9是正常的正向时长,但第一个示例的58:42.5到00:02.3得到负数),可能需要判断是否是跨了一个小时的情况,可以通过添加pd.Timedelta(hours=1)来修正:# 修正跨小时的情况:如果ended_at < started_at,就给ended_at加1小时 mask = merged['ended_at'] < merged['started_at'] merged.loc[mask, 'ended_at'] += pd.Timedelta(hours=1) merged['duration'] = merged['ended_at'] - merged['started_at']
- 如果你的业务场景中,
这样处理后,你就能顺利完成时间列的转换和时长计算啦!
内容的提问来源于stack exchange,提问作者kaecvtionr




