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

Mac环境下如何加速DataFrame大规模循环条件统计运行速度

Mac环境千万行级数据15分钟粒度站点统计提速方案

问题基础信息

  • 运行环境:Mac
  • 原始数据:1100万行共享单车租赁记录DataFrame,单条行数据对应1次取车行为
  • 目标产出:157954行、365列的统计矩阵,行维度为15分钟间隔的时间点,列维度为367个取车站点,单元格值为对应时间窗内的站点取车量;后续还需基于原始数据计算平均骑行速度、平均骑行时长等衍生指标
  • 当前现状:手写双层循环实现逻辑,运行时长已超10小时
    现有运行耗时截图

当前实现代码如下:

for station in stations:
    no_pickup_array = []
    for time_point in data_matrix['Timestamp']:
        time_point_2 = time_point + timedelta(minutes=15)
        no_pickup = len(dataframe[(time_point <= dataframe["departure"]) & (dataframe["departure"] < time_point_2) 
                        & (dataframe['departure_name'] == station)])
        no_pickup_array.append(no_pickup)
    print(f"Station name: {station}")
    data_matrix[station] = no_pickup_array

原始DataFrame示例

核心性能瓶颈

现有代码总计算量为367个站点×157954个时间点≈5800万次全表扫描,每次扫描都要遍历1100万行全量数据做条件过滤,Python层循环本身无编译优化,整体计算量达到万亿级操作,耗时过长是必然结果。

可行提速方案(按实现难度从低到高排序)

方案1:pandas原生分组重采样(代码改动量最小,提速1000倍以上,预计10~60秒出结果)

该方案完全适配你的统计场景,不需要手写循环,pandas底层为C实现的分组、时间窗聚合逻辑,性能远高于手写Python循环。后续计算平均骑行速度、时长等指标也可以直接扩展,不需要重写逻辑。
实现代码:

import pandas as pd

# 统一转换时间字段类型(未转时间类型会导致后续计算性能暴跌)
dataframe['departure'] = pd.to_datetime(dataframe['departure'])

# 按站点+15分钟时间窗聚合统计取车量
count_result = (
    dataframe
    .set_index('departure')
    .groupby('departure_name')
    .resample('15min')
    .size() # 统计窗口内记录数,即取车量;后续算平均指标可替换为.agg({'speed':'mean', 'duration':'mean'})
    .unstack(level=0) # 将站点维度从行索引转为列,生成时间点×站点的矩阵结构
)

# 对齐预设的Timestamp索引,无取车记录的时间点填充0
data_matrix = data_matrix.set_index('Timestamp')
final_result = data_matrix.join(count_result, how='left').fillna(0)

方案2:预分组索引+二分查找优化(比方案1快2~3倍,适合后续自定义窗口计算场景)

之前提到的索引构建思路存在代码笔误,修正后逻辑为:提前按站点拆分全量数据,每个站点的取车时间预先排序,统计时不再扫描全表,仅在对应站点的有序时间数组中通过二分查找定位时间窗边界,两个边界的下标差值即为窗口内取车量,不需要遍历数组内所有元素。
实现代码:

import pandas as pd
import numpy as np
from bisect import bisect_left

# 预构建站点时间索引
station_time_map = {}
for station_name, station_df in dataframe.groupby('departure_name'):
    # 每个站点仅保留排序后的取车时间numpy数组,减少内存占用、加速查找
    sorted_time_arr = np.sort(station_df['departure'].to_numpy())
    station_time_map[station_name] = sorted_time_arr

# 遍历统计
data_matrix = data_matrix.set_index('Timestamp')
for station in stations:
    time_arr = station_time_map[station]
    count_list = []
    for tp in data_matrix.index:
        tp_end = tp + pd.Timedelta(minutes=15)
        # 二分查找定位时间窗左右边界
        left_pos = bisect_left(time_arr, tp)
        right_pos = bisect_left(time_arr, tp_end)
        count_list.append(right_pos - left_pos)
    data_matrix[station] = count_list

该方案总计算量仅为367次单站点数据排序+5800万次二分查找(单次数组查找仅需15次左右比较操作),总计算量不到原有实现的百万分之一,运行耗时可压缩至数秒级别。

Mac环境专属优化技巧

  • 优先通过conda安装带OpenBLAS/MKL优化的pandas、numpy版本,相比pip默认安装版本,数组运算速度可提升2~3倍
  • 提前提取计算需要的核心字段(如departure、departure_name、骑行速度、骑行时长),丢弃无关列,降低内存占用,避免内存不足触发磁盘交换拖慢速度
  • 所有聚合、窗口计算优先使用pandas原生方法,不要在Python层手写循环做逐行过滤判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 06:48:21