Python业务转化率计算代码优化:替代多层循环提升执行效率
高效计算多维度销售转化率(替代多层循环方案)
核心思路
利用pandas的groupby聚合能力替代嵌套循环,通过向量式运算完成多维度分组统计,从根本上解决循环导致的性能问题。关键步骤:
- 将业务时间字段转换为
YYYYMM格式,匹配指定时间范围 - 按年月、销售者、产品、业务规模、元素数量5个维度分组
- 一次性聚合计算创建/赢单/输单的数量与金额
- 基于聚合结果计算数量和金额维度的转化率
高效实现代码
import pandas as pd # 假设原始数据集df包含以下字段: # fecha_creacion(业务创建时间)、fecha_ganado(赢单时间)、fecha_perdido(输单时间) # Negocio_Propietario、Negocio_Producto、Tamano_de_Negocio、Cantidad_de_Elementos # monto(业务金额) # 1. 转换时间为年月格式(YYYYMM)并过滤范围 df['year_month'] = df['fecha_creacion'].dt.strftime('%Y%m').astype(int) df_filtered = df[(df['year_month'] >= 201707) & (df['year_month'] <= 202308)].copy() # 2. 标记赢单/输单状态(用于聚合统计) df_filtered['is_won'] = df_filtered['fecha_ganado'].notna().astype(int) df_filtered['is_lost'] = df_filtered['fecha_perdido'].notna().astype(int) # 3. 多维度分组聚合 grouped_stats = df_filtered.groupby([ 'year_month', 'Negocio_Propietario', 'Negocio_Producto', 'Tamano_de_Negocio', 'Cantidad_de_Elementos' ]).agg( total_created=('is_won', 'count'), total_won=('is_won', 'sum'), total_lost=('is_lost', 'sum'), amount_created=('monto', 'sum'), amount_won=('monto', lambda x: x[df_filtered.loc[x.index, 'is_won'] == 1].sum()), amount_lost=('monto', lambda x: x[df_filtered.loc[x.index, 'is_lost'] == 1].sum()) ).reset_index() # 4. 计算转化率,处理除零场景 grouped_stats['win_rate_count'] = grouped_stats['total_won'] / grouped_stats['total_created'].replace(0, pd.NA) grouped_stats['lose_rate_count'] = grouped_stats['total_lost'] / grouped_stats['total_created'].replace(0, pd.NA) grouped_stats['win_rate_amount'] = grouped_stats['amount_won'] / grouped_stats['amount_created'].replace(0, pd.NA) grouped_stats['lose_rate_amount'] = grouped_stats['amount_lost'] / grouped_stats['amount_created'].replace(0, pd.NA) # 填充空值为0(按需调整) grouped_stats.fillna(0, inplace=True)
原低效循环实现示例
# 假设原始数据为列表格式data_list,每个元素是业务字典 result = [] # 多层嵌套循环遍历所有维度组合 for year_month in range(201707, 202309): for propietario in set(item['Negocio_Propietario'] for item in data_list): for producto in set(item['Negocio_Producto'] for item in data_list): for tamano in set(item['Tamano_de_Negocio'] for item in data_list): for cantidad in set(item['Cantidad_de_Elementos'] for item in data_list): # 筛选当前维度的业务数据 filtered_data = [ item for item in data_list if pd.to_datetime(item['fecha_creacion']).strftime('%Y%m') == str(year_month) and item['Negocio_Propietario'] == propietario and item['Negocio_Producto'] == producto and item['Tamano_de_Negocio'] == tamano and item['Cantidad_de_Elementos'] == cantidad ] if not filtered_data: continue # 手动统计数量与金额 total_created = len(filtered_data) total_won = sum(1 for item in filtered_data if item['fecha_ganado'] is not None) total_lost = sum(1 for item in filtered_data if item['fecha_perdido'] is not None) amount_created = sum(item['monto'] for item in filtered_data) amount_won = sum(item['monto'] for item in filtered_data if item['fecha_ganado'] is not None) amount_lost = sum(item['monto'] for item in filtered_data if item['fecha_perdido'] is not None) # 计算转化率 win_rate_count = total_won / total_created if total_created !=0 else 0 lose_rate_count = total_lost / total_created if total_created !=0 else 0 win_rate_amount = amount_won / amount_created if amount_created !=0 else 0 lose_rate_amount = amount_lost / amount_created if amount_created !=0 else 0 # 存入结果 result.append({ 'year_month': year_month, 'Negocio_Propietario': propietario, 'Negocio_Producto': producto, 'Tamano_de_Negocio': tamano, 'Cantidad_de_Elementos': cantidad, 'total_created': total_created, 'total_won': total_won, 'total_lost': total_lost, 'amount_created': amount_created, 'amount_won': amount_won, 'amount_lost': amount_lost, 'win_rate_count': win_rate_count, 'lose_rate_count': lose_rate_count, 'win_rate_amount': win_rate_amount, 'lose_rate_amount': lose_rate_amount })
效率差异说明
- 原循环写法为**O(n^5)**复杂度(5个维度嵌套循环),数据量超过万级后会出现明显卡顿
- pandas方案基于C底层向量运算,复杂度接近O(n),百万级数据也能在几秒内完成计算
- 避免了多次重复筛选数据,所有统计逻辑一次性完成,大幅减少IO与计算开销
内容的提问来源于stack exchange,提问作者alexis gonzalez
相关产品推荐
相关产品推荐

