如何实现两个DataFrame匹配列行相乘后按行求和生成新DataFrame?
问题需求
我有两个Pandas DataFrame:
import pandas as pd df1 = pd.DataFrame( {'spot': [1,2,3], 'ID1': [0,1,0], 'ID2': [1, 1, 2], 'ID3': [0,0,1]}) df2 = pd.DataFrame( {'ID': ['ID1','ID2','ID3'], 'prop1': [0.01,0.8,0.0], 'prop2': [0.0, 0.04, 0.5]})
df1输出:
spot ID1 ID2 ID3 0 1 0 1 0 1 2 1 1 0 2 3 0 2 1
df2输出:
ID prop1 prop2 0 ID1 0.01 0.00 1 ID2 0.80 0.04 2 ID3 0.00 0.50
中间预期效果(仅作示意):
spot ID1 ID2 ID3 0 1 0 [1*0.8, 1*0.04] 0 1 2 [1*0.01, 1*0.0] [1*0.8, 1*0.04] 0 2 3 0 [2*0.8, 2*0.04] [1*0.0, 1*0.5]
最终希望生成包含
spot、prop1、prop2的DataFrame,其中每行的prop1为所有ID列对应prop1乘积之和,prop2同理:
spot prop1 prop2 0 1 (1*0.8) (1*0.04) 1 2 (1*0.01 + 1*0.8) (1*0.04) 2 3 (2*0.8 + 0) (2*0.04 + 1*0.5)
尝试的代码(未得到预期结果):
arr = df1.iloc[:, 1:].to_numpy() arr2 = df2.iloc[:, 1:].to_numpy() for i in range(len(arr)): for j in range(len(arr)): print(arr[i, j] * arr2[i])
解决方案
不需要嵌套循环,直接利用Pandas的广播和矩阵运算就能高效实现:
核心实现(直接得到数值结果)
# 提取df1的ID数值部分,以spot为索引 df1_ids = df1.set_index('spot') # 提取df2的prop数值部分,以ID为索引后转置,让prop类型成为行、ID成为列 df2_props = df2.set_index('ID').T # 矩阵乘法:自动完成每行ID值与对应prop的乘积求和 result = df1_ids @ df2_props # 合并spot列并重置索引 final_df = result.reset_index() print(final_df)
输出结果:
spot prop1 prop2 0 1 0.80 0.04 1 2 0.81 0.04 2 3 1.60 0.58
带计算过程的示意输出
如果需要像需求里那样显示求和表达式,可以额外生成字符串列:
prop1_expr = [] prop2_expr = [] for _, row in df1.iterrows(): p1_parts = [] p2_parts = [] # 遍历每个ID列,收集非零值的计算项 for col in ['ID1', 'ID2', 'ID3']: val = row[col] if val == 0: continue # 匹配df2中对应ID的prop值 p1 = df2.loc[df2['ID'] == col, 'prop1'].values[0] p2 = df2.loc[df2['ID'] == col, 'prop2'].values[0] p1_parts.append(f"{val}*{p1}") p2_parts.append(f"{val}*{p2}") # 拼接成表达式字符串 prop1_expr.append(f"({' + '.join(p1_parts)})" if p1_parts else "(0)") prop2_expr.append(f"({' + '.join(p2_parts)})" if p2_parts else "(0)") # 添加到结果中 final_df['prop1_expr'] = prop1_expr final_df['prop2_expr'] = prop2_expr print(final_df[['spot', 'prop1_expr', 'prop2_expr']])
输出:
spot prop1_expr prop2_expr 0 1 (1*0.8) (1*0.04) 1 2 (1*0.01 + 1*0.8) (1*0.04) 2 3 (2*0.8) (2*0.04 + 1*0.5)
原代码问题说明
原代码的嵌套循环索引逻辑错误:j遍历的是行数而非列数,且arr2[i]取的是df2的第i行,实际应该取df2的第j行(对应df1的第j个ID列);同时缺少对每行乘积的求和操作,导致无法得到目标结果。
内容的提问来源于stack exchange,提问作者kas
相关产品推荐
相关产品推荐

