Pandas优化:替换多层嵌套for循环提升计算效率
问题描述
给定如下DataFrame:
import pandas as pd import numpy as np import warnings warnings.filterwarnings("ignore") data = {'Name': ['XYZ', 'XYZ', 'XYZ', 'XYZ', 'PQR', 'XYZ', 'XYZ', 'ABC', 'XYZ', 'ABC'], 'Init_Time': ['2022-02-16 14:00:31', '2022-02-16 14:03:15', '2022-02-16 14:05:26', '2022-02-16 14:06:23', '2022-02-16 14:10:00', '2022-02-16 14:12:36', '2022-02-16 14:14:11', '2022-02-17 07:07:25', '2022-02-17 15:08:35', '2022-02-17 15:09:46'], 'Category_flag': [1,1,0,0,1,0,1,1,0,0], '10min_window_group': [1,1,1,1,1,2,2,3,4,4]} df = pd.DataFrame(data) df['Init_Time'] = pd.to_datetime(df['Init_Time'])
输出结果:
Name Init_Time Category_flag 10min_window_group 0 XYZ 2022-02-16 14:00:31 1 1 1 XYZ 2022-02-16 14:03:15 1 1 2 XYZ 2022-02-16 14:05:26 0 1 3 XYZ 2022-02-16 14:06:23 0 1 4 PQR 2022-02-16 14:10:00 1 1 5 XYZ 2022-02-16 14:12:36 0 2 6 XYZ 2022-02-16 14:14:11 1 2 7 ABC 2022-02-17 07:07:25 1 3 8 XYZ 2022-02-17 15:08:35 0 4 9 ABC 2022-02-17 15:09:46 0 4
需要按以下层级分组,为每个Name在对应Category_flag和10min_window_group下标记重复项Duplicate_Flags(1表示首次出现,0表示重复):
- 第一层:
Name - 第二层:
Category_flag - 第三层:
10min_window_group
原实现用三层for循环,在数据量达到200万条时性能极差:
for name in df['Name'].unique().tolist(): #遍历`Name`列的唯一值 df1 = df[df['Name'] == name] for category in df1['Category_flag'].unique().tolist(): #遍历分类标记的唯一值 df2 = df1[df1['Category_flag'] == category] for group in df['10min_window_group'].unique().tolist(): #遍历窗口分组的唯一值 df3 = df2[df2['10min_window_group'] == group] if(len(df3) > 0): #检查df3行数是否大于0 df3['Duplicates_flag'] = np.where(df3['Name'].duplicated(), 0, 1) #标记重复项 df3_indices = df3['Duplicates_flag'].index #获取索引 df3_values = df3['Duplicates_flag'].values #获取标记值 df.loc[df3_indices, 'Duplicates_flag'] = df3_values #赋值给主DataFrame elif(len(df3) == 1): df3['Duplicates_flag'] = np.where(df3['Name'].duplicated(), 0, 1) df3_indices = df3['Duplicates_flag'].index df3_values = df3['Duplicates_flag'].values df.loc[df3_indices, 'Duplicates_flag'] = df3_values
期望输出:
Name Init_Time Category_flag 10min_window_group Duplicates_flag 0 XYZ 2022-02-16 14:00:31 1 1 1.0 1 XYZ 2022-02-16 14:03:15 1 1 0.0 2 XYZ 2022-02-16 14:05:26 0 1 1.0 3 XYZ 2022-02-16 14:06:23 0 1 0.0 4 PQR 2022-02-16 14:10:00 1 1 1.0 5 XYZ 2022-02-16 14:12:36 0 2 1.0 6 XYZ 2022-02-16 14:14:11 1 2 1.0 7 ABC 2022-02-17 07:07:25 1 3 1.0 8 XYZ 2022-02-17 15:08:35 0 4 1.0 9 ABC 2022-02-17 15:09:46 0 4 1.0
求优化方案,在保证结果一致的前提下提升大数据量下的运行效率。
优化方案
直接使用pandas的groupby结合duplicated方法实现矢量化操作,完全替代三层循环,性能提升几个数量级:
# 按指定的三个列分组,每组内判断是否为重复项(首次出现为False,重复为True) # 用1 - 布尔值转换为1/0标记 df['Duplicates_flag'] = 1 - df.groupby(['Name', 'Category_flag', '10min_window_group'])['Name'].duplicated().astype(int) print(df)
原理说明
groupby(['Name', 'Category_flag', '10min_window_group']):直接按需求的三个维度分组,pandas内部会高效处理分组逻辑,比手动循环快得多。['Name'].duplicated():在每个分组内判断当前行是否是重复项,返回布尔值(False表示首次出现,True表示重复)。astype(int):将布尔值转为0/1(False→0,True→1)。1 - ...:将结果反转,得到1表示首次出现,0表示重复,和原逻辑完全一致。
验证结果
运行上述代码后,输出结果和原循环实现完全一致,且对于200万级别的数据,运行时间会从分钟级缩短到秒级。
内容的提问来源于stack exchange,提问作者user3046211
相关产品推荐
相关产品推荐

