pandas实现多列DataFrame与单值/单行DataFrame减法的方法
Pandas 非等规格DataFrame减法实现方案
核心逻辑说明
直接执行df1 - df2无法得到预期结果的根本原因是:pandas 执行算术运算时,会严格按照两边对象的行标签、列标签一一匹配后再计算,只要标签对不上的位置,运算结果就会返回缺失值NaN,不会像numpy那样只看数组形状自动广播。要实现题目要求的广播减法,要么绕开标签对齐直接基于值计算,要么主动指定标签匹配规则让值自动广播。
场景1:多列DataFrame 减 单值DataFrame
问题复现
如果直接执行df1 - df2会得到全为NaN的结果:因为df1的列标签是OUT1~OUT6,df2没有自定义列标签、默认列为整数0,两者列标签完全不匹配,无法对齐运算。
可行实现方案
- 方案1:提取单值做标量运算
因为df2是单元素DataFrame,直接取出存储的标量值和df1做减法即可,运算后会自动和整个DataFrame广播:result = df1 - df2.iloc[0, 0] - 方案2:基于numpy值数组运算,跳过标签对齐
直接取出两个DataFrame的底层值数组(numpy array),利用numpy的广播规则计算后,再按照df1的索引、列名重建DataFrame:
该方法完全不受标签不匹配的影响,结果和预期完全一致。result = pd.DataFrame( data = df1.values - df2.values, index = df1.index, columns = df1.columns )
场景2:多行多列DataFrame 减 列标签不匹配的单行多列DataFrame
问题复现
直接执行df1 - df2同样会得到大量NaN:df1列标签为OUT1`OUT6`,`df2`默认列标签为整数05,列标签无法一一对应,无法完成逐列减法。
可行实现方案
- 方案1:基于numpy值数组运算(最通用)
df1.values形状为(2,6),df2.values形状为(1,6),numpy会自动将单行的减数值组沿着行方向广播,和df1的每一行做逐元素减法,计算后重建DataFrame即可:
运行后得到的结果为:result = pd.DataFrame( data = df1.values - df2.values, index = df1.index, columns = df1.columns )
和预期输出完全匹配。OUT1 OUT2 OUT3 OUT4 OUT5 OUT6 0 0 0 0 0 0 0 1 6 6 6 6 6 6 - 方案2:对齐标签后用pandas内置的广播规则运算
先把df2的列标签改成和df1完全一致,再用sub()方法指定按列维度匹配标签、自动广播行维度的值:
该方法不需要转换numpy数组,全程在pandas结构内完成运算,性能和原生计算一致。# 统一列标签 df2.columns = df1.columns # 按列轴匹配标签,单行值自动广播到df1的所有行 result = df1.sub(df2, axis='columns')
注意:pandas中
axis参数的指向为“需要匹配标签的维度”,比如axis='columns'代表按列标签匹配,值会沿着行维度广播;axis='index'代表按行标签匹配,值会沿着列维度广播,不要和numpy的广播方向记混。
内容的提问来源于stack exchange,提问作者enteng_kamote
相关产品推荐
相关产品推荐

