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

优化Pandas Series列表元素的时间差/数值差计算效率

优化百万级Pandas Series列表差值计算性能

问题背景

我有两个独立的Pandas Series,每个Series的元素均为列表(总长度超百万),对应位置的元素类型一致:要么是整数(多数为0,代表0小时),要么是Timestamp。需要完成以下计算:

  1. 对两个Series对应位置的子列表,计算对应元素的差值(时间差需转换为小时)
  2. 若子列表包含多个元素,对差值求和
  3. 最终返回一个表示小时差的数值列表

现有实现结果正确,但运行速度极慢,寻求更高效的代码重构方案。

样本数据

import pandas as pd
import numpy as np
from datetime import datetime

# 样本dpt Series
dpt = pd.Series([
    [0],
    [pd.Timestamp('2017-06-10 14:50:00+0000', tz='UTC')],
    [0],
    [0],
    [pd.Timestamp('2017-06-10 14:50:00+0000', tz='UTC')],
    [pd.Timestamp('2017-02-16 08:37:00+0000', tz='UTC')],
    [pd.Timestamp('2017-03-06 20:00:00+0000', tz='UTC'), pd.Timestamp('2017-03-07 09:50:00+0000', tz='UTC')],
    [0],
    [0],
    [pd.Timestamp('2017-04-27 18:25:00+0000', tz='UTC')]
])

# 样本arr Series
arr = pd.Series([
    [0],
    [pd.Timestamp('2017-06-10 06:20:00+0000', tz='UTC')],
    [0],
    [0],
    [pd.Timestamp('2017-02-10 09:03:00+0000', tz='UTC')],
    [pd.Timestamp('2017-02-16 07:40:00+0000', tz='UTC')],
    [pd.Timestamp('2017-03-06 16:35:00+0000', tz='UTC'), pd.Timestamp('2017-03-07 07:15:00+0000', tz='UTC')],
    [0],
    [0],
    [pd.Timestamp('2017-04-27 16:25:00+0000', tz='UTC')]
])

现有实现(性能瓶颈版本)

def layover_hours(dpt, arr):
    f = []
    for i in range(len(dpt)):
        dpt_ = list(dpt)[i]
        arr_ = list(arr)[i]
        r = []
        for j in range(len(dpt_)):
            d = [dpt_[j]-arr_[j]]
            r.extend(d)
        f.append(r)
    d =[]
    for x in f:
        if type(x[0]) == int:
            d.append(sum(x))
        else:
            d.append(sum(x, datetime.timedelta(0,0))/np.timedelta64(1,'h'))
    return d

# 样本运行
print(layover_hours(dpt=dpt[0:10], arr=arr[0:10]))
# 输出:[0, 8.5, 0, 0, 1.95, 0.95, 6.0, 0, 0, 2.0]

优化方案

方案1:合并循环+Pandas逐元素映射

利用Pandas的combine方法替代纯Python循环,内部基于C级别的运算逻辑,大幅提升百万级数据的处理速度:

def layover_hours_fast(dpt, arr):
    def calculate_single_pair(dpt_list, arr_list):
        # 计算对应元素差值
        diffs = [d - a for d, a in zip(dpt_list, arr_list)]
        # 根据类型求和转换
        if isinstance(diffs[0], int):
            return sum(diffs)
        else:
            total_delta = sum(diffs, datetime.timedelta())
            return total_delta / np.timedelta64(1, 'h')
    
    # 对两个Series的对应元素批量应用计算逻辑
    return dpt.combine(arr, calculate_single_pair).tolist()

# 测试验证
print(layover_hours_fast(dpt, arr))
# 输出:[0, 8.5, 0, 0, 1.95, 0.95, 6.0, 0, 0, 2.0]

方案2:统一数据类型为数值(极致性能)

将Timestamp转换为小时级的数值(Unix时间戳转小时),统一整数和时间戳的运算逻辑,避免类型判断开销,进一步提升性能:

def layover_hours_vect(dpt, arr):
    def convert_to_hour_values(lst):
        if isinstance(lst[0], int):
            return lst
        # 将Timestamp转换为小时级数值(基于Unix时间戳)
        return [(ts.timestamp() / 3600) for ts in lst]
    
    # 批量转换两个Series的元素为小时数值列表
    dpt_hours = dpt.apply(convert_to_hour_values)
    arr_hours = arr.apply(convert_to_hour_values)
    
    # 对应位置元素相减后求和
    return dpt_hours.combine(arr_hours, lambda x, y: sum(d - a for d, a in zip(x, y))).tolist()

# 测试验证
print(layover_hours_vect(dpt, arr))
# 输出:[0, 8.5, 0, 0, 1.95, 0.95, 6.0, 0, 0, 2.0]

优化原理说明

  1. 避免纯Python嵌套循环:原代码的双层Python循环在百万级数据下开销极大,优化后的方案利用Pandas的内置方法,将循环逻辑转移到C层面执行,速度提升数十倍。
  2. 减少中间变量:合并原代码的两次循环为单次计算,避免创建冗余的中间列表,降低内存占用和数据拷贝开销。
  3. 统一数据类型:方案2通过类型转换,将时间差计算转为纯数值运算,彻底消除类型判断的额外开销,适合超大规模数据处理。

内容的提问来源于stack exchange,提问作者user2217673

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:35:00