You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas中使用apply函数基于计算值同时更新多列的实现方法及性能疑问

Pandas中使用apply函数基于计算值同时更新多列的实现方法及性能疑问

嗨,我来帮你解决这个问题!首先咱们先搞定用apply同时更新多列的需求,之后再聊聊你关心的性能问题。

一、用apply同时生成多列的解决方案

你现在的calculate_time_diff函数只返回了时间差字符串,但其实可以让它返回元组,包含秒数和格式化后的字符串,之后直接把这个元组的结果拆解到两个列里就行。另外注意你代码里有个小笔误:str_event_time定义了,但用的时候写成了str_t_zero_time,这个得先修正;还有原时间字符串里的011应该是11的手误,我也一起调整了。

修正后的完整代码

from datetime import datetime
import pandas as pd

# 修正笔误:变量名统一、时间格式修正
str_event_time = '2025-01-24T11:55:00.000Z'
event_time = datetime.strptime(str_event_time,'%Y-%m-%dT%H:%M:%S.%fZ')

def calculate_time_diff(date_time):
    # 计算时间差秒数
    time_diff_secs = (date_time - event_time).total_seconds()
    
    # 计算时分秒格式
    m, s = divmod(abs(time_diff_secs), 60)
    h, m = divmod(m, 60)
    
    # 根据正负号处理小时部分
    sign_h = h if time_diff_secs >= 0 else -h
    time_diff_string = 'T{:+03.0f}:{:02.0f}:{:05.2f}'.format(sign_h, m, s)
    
    # 返回元组:(秒数, 格式化字符串)
    return time_diff_secs, time_diff_string 

def main():
    # 构造测试数据框
    df = pd.DataFrame({
        'date_time': [
            '2025-01-24 12:00:00.000',
            '2025-01-24 12:05:00.000',
            '2025-01-24 12:10:00.000'
        ]
    })
    # 先把date_time转成datetime类型,不然没法做时间差计算
    df['date_time'] = pd.to_datetime(df['date_time'])
    
    # 用apply返回元组,直接拆解到两列
    df['time_diff_s'], df['time_delta'] = zip(*df['date_time'].apply(calculate_time_diff))
    
    # 调整列顺序到你想要的样子
    df = df[['time_diff_s', 'time_delta', 'date_time']]
    print(df)
    # 保存到Excel
    df.to_excel('time_diff_result.xlsx', index=False)

if __name__ == '__main__':
    main()

关键说明

  • 让函数返回包含两个值的元组,这样apply会给每一行返回一个元组;
  • 用zip(*...)把所有行的元组拆解成两个独立的序列,分别赋值给time_diff_s和time_delta列;
  • 必须先把date_time列转成datetime类型,否则无法进行时间差计算。

二、关于apply和循环的性能对比

你提到疑惑apply和循环哪个更高效,其实得明确几点:

  • apply本质上还是逐行循环,只是把循环封装在了Pandas的接口里,性能和手动写for循环差别不大,甚至有时候还不如手动循环(因为有额外的函数调用开销);
  • Pandas最推荐的是向量化操作,完全避免逐行循环,利用底层的C语言实现,性能会比apply/手动循环快很多倍,尤其当数据量很大的时候。

向量化实现的版本(更高效)

咱们可以不用apply,直接对整个列做向量化计算:

from datetime import datetime
import pandas as pd

def main():
    str_event_time = '2025-01-24T11:55:00.000Z'
    event_time = datetime.strptime(str_event_time,'%Y-%m-%dT%H:%M:%S.%fZ')
    
    # 构造测试数据框并转换时间类型
    df = pd.DataFrame({
        'date_time': [
            '2025-01-24 12:00:00.000',
            '2025-01-24 12:05:00.000',
            '2025-01-24 12:10:00.000'
        ]
    })
    df['date_time'] = pd.to_datetime(df['date_time'])
    
    # 向量化计算时间差秒数
    df['time_diff_s'] = (df['date_time'] - event_time).dt.total_seconds()
    
    # 向量化计算时分秒各部分
    abs_secs = df['time_diff_s'].abs()
    hours = abs_secs // 3600
    minutes = (abs_secs % 3600) // 60
    seconds = abs_secs % 60
    
    # 处理符号并格式化字符串
    sign = df['time_diff_s'].apply(lambda x: '+' if x >=0 else '-')
    df['time_delta'] = 'T' + sign + hours.astype(int).apply('{:02d}'.format) + ':' + \
                      minutes.astype(int).apply('{:02d}'.format) + ':' + \
                      seconds.apply('{:05.2f}'.format)
    
    # 调整列顺序
    df = df[['time_diff_s', 'time_delta', 'date_time']]
    print(df)
    df.to_excel('time_diff_result.xlsx', index=False)

if __name__ == '__main__':
    main()

这个版本里,核心的时间差计算都是向量化的,只有最后处理符号和格式化时用了两次轻量的apply,数据量越大,这个版本的性能优势越明显。

总结

  • 如果只是小数据量,用apply实现多列更新完全没问题,代码更直观易读;
  • 如果数据量较大,优先用向量化操作,性能会提升一个量级;
  • apply和手动循环的性能差异不大,不要误以为apply是“高效”的循环,它只是写法更简洁而已。

备注:内容来源于stack exchange,提问作者D Chase

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 15:08:14