Python中高效实现Excel SUMIF等价功能的优化问询
问题:Python实现高效SUMIF替代方案
我正在用Python实现Excel的SUMIF等价功能,当前代码能运行但效率极低,耗时长达20分钟。以下是简化后的代码和数据示例(实际代码包含更多条件),寻求最高效的实现方法。
数据示例
sales_data(customer_1)
| Transactions | Product Dimension 4 | Product Dimension 2 | Product Dimension 3 | sum_of_sales |
|---|---|---|---|---|
| 1 | 50 | F80 | ETQ546 | 80 |
| 2 | 50 | F80 | SAS978 | 20 |
| 3 | 50 | C36 | JBH148 | 10 |
| 4 | 50 | F80 | ETQ546 | 80 |
| 5 | 50 | F80 | SAS978 | 20 |
| 6 | 50 | C36 | JBH148 | 10 |
| 7 | 20 | A20 | OPW269 | 15 |
| 8 | 20 | A20 | DUW987 | 65 |
| 9 | 20 | v90 | OWQ897 | 47 |
condition_types(添加SUMIF前)
| Transactions | Type | Product Dimensions |
|---|---|---|
| customer_1 | ABC | 50 |
| customer_1 | DEF | F80 |
| customer_1 | GHI | JBH148 |
condition_types(添加SUMIF后)
| Transactions | Type | Product Dimensions | sum_of_sales |
|---|---|---|---|
| customer_1 | ABC | 50 | 220 |
| customer_1 | DEF | F80 | 200 |
| customer_1 | GHI | JBH148 | 20 |
原低效代码
定义SUMIF函数
def sumif(row, value_column): if row['Type'] == "ABC": filtered_data = sales_data.loc[ (sales_data['Product_dimension_4'] == row['Product Dimensions']) ] elif row['Type'] == "DEF" and row['Product Dimensions'] in sales_data['Product_dimension_2'].unique(): filtered_data = sales_data.loc[ (sales_data['Product_dimension_2'] == row['Product Dimensions']) ] elif row['Type'] == "GHI" and row['Product Dimensions'] in sales_data['Product_dimension_3'].unique(): filtered_data = sales_data.loc[ (sales_data['Product_dimension_3'] == row['Product Dimensions']) ] else: return 0 # 返回0而非空值以保证一致性 return filtered_data[value_column].sum()
应用函数
condition_types['sum_of_sales'] = condition_types.apply(lambda row: sumif(row, value_column="sum_of_sales"), axis=1)
高效优化方案
原代码慢的核心原因是逐行循环+重复过滤全表,每次apply都会遍历整个sales_data,时间复杂度为O(M*N)(M是condition_types行数,N是sales_data行数)。优化思路是预计算各维度的求和结果,再通过字典映射快速查找,时间复杂度降为O(M+N)。
步骤1:预计算各维度求和字典
# 预计算每个维度的sum_of_sales总和,转为字典 dim4_sum = sales_data.groupby('Product Dimension 4')['sum_of_sales'].sum().to_dict() dim2_sum = sales_data.groupby('Product Dimension 2')['sum_of_sales'].sum().to_dict() dim3_sum = sales_data.groupby('Product Dimension 3')['sum_of_sales'].sum().to_dict()
步骤2:快速映射计算结果
用np.select实现多条件快速映射:
import numpy as np # 定义条件列表和对应的值列表 conditions = [ condition_types['Type'] == 'ABC', condition_types['Type'] == 'DEF', condition_types['Type'] == 'GHI' ] choices = [ condition_types['Product Dimensions'].map(dim4_sum).fillna(0), condition_types['Product Dimensions'].map(dim2_sum).fillna(0), condition_types['Product Dimensions'].map(dim3_sum).fillna(0) ] # 应用映射 condition_types['sum_of_sales'] = np.select(conditions, choices, default=0)
优化优势
groupby.sum()仅遍历一次sales_data,完成所有分组求和的预计算map基于哈希表实现O(1)查找,远快于逐行过滤全表的操作- 消除了原代码中重复调用
unique()的额外性能开销
若实际代码有更多Type条件,只需扩展conditions和choices列表即可,保持同样的高效性。
内容的提问来源于stack exchange,提问作者nicgl
相关产品推荐
相关产品推荐

