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

如何用groupby+apply重构百万级数据集Flag2生成循环并优化性能?

解决方案

1. 结合GroupBy与Apply实现原循环逻辑

首先确保数据按ID和时间顺序排列,再针对每个ID分组执行原循环逻辑:

步骤1:数据预处理

import pandas as pd
import numpy as np

# 将Period转换为datetime类型,保证排序正确性
df['Period'] = pd.to_datetime(df['Period'], format='%b-%y')
# 按ID和Period排序,确保每个ID的行是时间有序的
df = df.sort_values(['ID', 'Period']).reset_index(drop=True)

步骤2:编写分组处理函数

def process_single_id(group):
    # 重置分组内索引为0-based,方便操作
    group = group.reset_index(drop=True).copy()
    group['Flag2'] = 0
    n_rows = len(group)
    i = 0
    while i < n_rows:
        if group.loc[i, 'Flag1'] == 1:
            # 计算标记的结束位置,不超过分组行数
            end_idx = min(i + 11, n_rows - 1)
            group.loc[i:end_idx, 'Flag2'] = 1
            # 跳11步,跳过中间不需要检查的行
            i += 11
        i += 1
    return group

步骤3:应用GroupBy

df = df.groupby('ID', group_keys=False).apply(process_single_id)

2. 性能更优的替代方案

原循环逻辑的瓶颈在于逐行操作,以下两种方法可大幅提升性能:

方法一:使用Numba加速循环

Numba可将Python循环编译为机器码,显著提升速度:

from numba import njit

# 用Numba装饰加速核心逻辑
@njit
def compute_flag2(flag1_array):
    n = len(flag1_array)
    flag2 = np.zeros(n, dtype=np.int32)
    i = 0
    while i < n:
        if flag1_array[i] == 1:
            end = min(i + 11, n - 1)
            flag2[i:end+1] = 1
            i += 11
        i += 1
    return flag2

def process_group_numba(group):
    group = group.reset_index(drop=True).copy()
    group['Flag2'] = compute_flag2(group['Flag1'].values)
    return group

# 应用到分组
df = df.groupby('ID', group_keys=False).apply(process_group_numba)

方法二:向量化标记起始位置

通过批量识别需要标记的起始点,再一次性设置Flag2,减少循环次数:

def process_group_vectorized(group):
    group = group.reset_index(drop=True).copy()
    n_rows = len(group)
    flag2 = np.zeros(n_rows, dtype=int)
    start_indices = []
    
    i = 0
    while i < n_rows:
        if group['Flag1'].iloc[i] == 1:
            start_indices.append(i)
            i += 11
        i += 1
    
    # 批量标记所有起始点对应的区间
    for s in start_indices:
        end = min(s + 11, n_rows - 1)
        flag2[s:end+1] = 1
    
    group['Flag2'] = flag2
    return group

df = df.groupby('ID', group_keys=False).apply(process_group_vectorized)

性能对比

  • 原逐行循环:80万行数据可能需要数分钟甚至更久
  • GroupBy+Apply:速度提升约5-10倍
  • Numba加速版本:速度提升约50-100倍,是处理超大数据集的最优选择

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 15:19:51