Pandas如何按数组长度复制DataFrame行并将值列与百分比相乘
问题背景
现有包含name、value列的pandas DataFrame对象df,以及存储多个百分比数值的数组,需要实现两个逻辑:
- 按照数组内的元素个数,复制df中的每一行
- 复制得到的每行
value值,依次与数组内的百分比相乘,得到最终计算结果
目前使用repeat方法实现存在逻辑静态、冗余的问题,需要更优的实现方案。
相关示例如下:
- 百分比数组定义
pct_list = [0.2, 0.5, 0.7]
- 原始DataFrame内容
name value 0 name1 20 1 name2 10
- 期望输出结果
name value 0 name1 4.0 1 name1 10.0 2 name1 14.0 3 name2 2.0 4 name2 5.0 5 name2 7.0
实现方案
直接用pandas交叉连接(笛卡尔积)实现即可,比repeat写法灵活,没有硬编码冗余,同时是原生向量化运算,性能足够好。
兼容所有pandas版本的写法
import pandas as pd # 原始数据 df = pd.DataFrame({'name': ['name1', 'name2'], 'value': [20, 10]}) pct_list = [0.2, 0.5, 0.7] # 构造带统一关联键的百分比临时表 pct_df = pd.DataFrame({'pct': pct_list, 'tmp_key': 1}) df['tmp_key'] = 1 # 关联得到笛卡尔积,自动按百分比数组长度复制所有行 res = df.merge(pct_df, on='tmp_key') # 计算新的value值,删除临时列 res['value'] = res['value'] * res['pct'] res = res.drop(columns=['tmp_key', 'pct']).reset_index(drop=True)
运行后输出和预期完全一致。
pandas 1.2.0+ 简化写法
高版本pandas原生支持cross连接,不需要手动加临时键,代码更短:
pct_df = pd.DataFrame({'pct': pct_list}) res = df.merge(pct_df, how='cross') res['value'] = res['value'] * res['pct'] res = res.drop(columns=['pct']).reset_index(drop=True)
方案优势
- 无硬编码:后续调整百分比数组的长度、数值,不需要修改核心逻辑,不会出现
repeat写法里写死复制次数导致的bug - 性能好:全流程pandas向量化运算,比循环、逐行apply的实现快几个量级,十万级以上数据也能快速处理
- 扩展性强:如果需要溯源每行计算对应的百分比,保留
pct列即可,不需要额外改逻辑
内容的提问来源于stack exchange,提问作者LearnerCode
相关产品推荐
相关产品推荐

