Pandas:对索引与列存在差异的DataFrame进行求和合并
解决Pandas多DataFrame相加时保留非交集值的问题
你的需求非常明确:两个DataFrame相加时,交集的索引和列要求和,仅在其中一个DataFrame存在的索引/列要保留原有值,而不是变成NaN。直接用+运算符确实会因为对齐后缺失值的问题产生NaN,不过用Pandas的add()方法就能完美解决这个问题。
问题分析
直接执行df1 + df2时,Pandas会先对齐两个DataFrame的索引和列:
- 只有同时存在于两个DataFrame的索引+列组合,才会执行求和。
- 只在其中一个DataFrame存在的位置,会被填充为
NaN(因为另一个DataFrame对应位置没有值),这就是你看到的data_3全是NaN、2016年索引的data_1是NaN的原因。
解决方案:使用add()方法并指定fill_value=0
add()是Pandas专门用于数据对齐后相加的方法,其中的fill_value参数可以指定当一方缺失值时用什么值填充,这样就能避免非交集位置变成NaN。
完整示例代码
import pandas as pd import numpy as np # 构建第一个DataFrame pi = pd.PeriodIndex(start=2017, periods=10, freq='M') a = pd.Series(np.full(shape=10, fill_value=2), pi) b = pd.Series(np.full(shape=10, fill_value=3), pi) df1 = pd.DataFrame({'data_1': a, 'data_2': b}) # 构建第二个DataFrame(更长索引+额外列) pi2 = pd.PeriodIndex(start=2016, periods=30, freq='M') a = pd.Series(np.full(shape=30, fill_value=2), pi2) b = pd.Series(np.full(shape=30, fill_value=3), pi2) c = pd.Series(np.full(shape=30, fill_value=3), pi2) df2 = pd.DataFrame({'data_1': a, 'data_2': b, 'data_3': c}) # 核心解决方案:用add方法并设置fill_value=0 new_df = df1.add(df2, fill_value=0) # 验证结果 print(new_df.iloc[0, 0]) # 输出 2.0(保留df2的原有值) print(new_df['data_3'].unique()) # 输出 [3.0](全保留df2的data_3值) print(new_df.loc['2017-01', 'data_1']) # 输出 4.0(df1和df2的2+2求和)
原理说明
- 对于同时存在于两个DataFrame的索引+列:正常执行求和操作(比如2017-01的data_1:2+2=4)。
- 对于仅在df2存在的索引/列:df1对应位置为NaN,用
fill_value=0填充后,0 + df2的值 = df2原有值,完美保留。 - 对于仅在df1存在的索引/列(如果有的话):df2对应位置用0填充,df1的值 + 0 = df1原有值,同样会保留。
可选:转换回整数类型
因为fill_value=0是浮点数,相加后的结果会变成float类型。如果需要整数,可以用astype(int)转换:
new_df = df1.add(df2, fill_value=0).astype(int)
内容的提问来源于stack exchange,提问作者Oliver
相关产品推荐
相关产品推荐

