合并含非公共列的DataFrame:300个数据集合并及空值填充咨询
批量合并多DataFrame并动态扩展列的解决方案
嘿,这个需求完全可以用Pandas的工具链轻松实现,我来给你一步步讲清楚操作逻辑,再附上可直接运行的代码示例:
核心思路拆解
你的需求本质是先把每个长格式的DataFrame转成宽格式(将Column_CounterName的取值转为列,Column_CounterValue对应填充),再批量合并所有宽格式DF,最后处理空值。这样就能自动保留所有新出现的列,同时对齐Column_A的取值。
步骤1:处理单个DataFrame(转宽格式)
对于每个输入的DataFrame,我们用pivot_table来转换格式——它能自动处理同一Column_A+CounterName组合的重复值(如果有的话,比如求和/取均值,你可以按需调整)。
示例代码:
import pandas as pd import numpy as np # 模拟你的示例DataFrame1 df1 = pd.DataFrame({ 'Column_A': ['a', 'a', 'b', 'b', 'd'], 'Column_CounterName': ['Type1', 'Type2', 'Type3', 'Type4', 'Type1'], 'Column_CounterValue': [100, 300, 356, 288, 453] # 修正原示例数值数量不一致问题 }) # 模拟DataFrame2 df2 = pd.DataFrame({ 'Column_A': ['m', 'm', 'n', 'n', 'o'], 'Column_CounterName': ['Type1', 'Type5', 'Type6', 'Type5', 'Type1'], 'Column_CounterValue': [100, 300, 356, 846, 7455] }) # 定义单个DF转宽格式的函数 def reshape_df(df): # 用pivot_table转宽,index是Column_A,columns是CounterName,values是CounterValue # aggfunc='first'表示如果有重复组合取第一个值,可换成sum/mean等 reshaped = df.pivot_table( index='Column_A', columns='Column_CounterName', values='Column_CounterValue', aggfunc='first' ).reset_index() # 把Column_A从索引转回列 # 重命名列,去掉多级索引的层级 reshaped.columns.name = None return reshaped # 测试单个转换 df1_reshaped = reshape_df(df1) df2_reshaped = reshape_df(df2)
转换后的df1_reshaped结构如下:
| Column_A | Type1 | Type2 | Type3 | Type4 |
|---|---|---|---|---|
| a | 100 | 300 | NaN | NaN |
| b | NaN | NaN | 356 | 288 |
| d | 453 | NaN | NaN | NaN |
步骤2:批量合并300个DataFrame
假设你把300个DataFrame存在一个列表df_list里,我们用pd.concat来合并——它会自动识别所有不同的列,把新出现的列自动添加进去,同时按Column_A对齐(如果有重复的Column_A取值,会自动合并行)。
代码示例:
# 假设你的300个DF都存在这个列表里(这里用两个示例模拟) df_list = [df1, df2] # 先批量转换所有DF为宽格式 reshaped_dfs = [reshape_df(df) for df in df_list] # 合并所有宽格式DF,按Column_A对齐,保留所有列 merged_df = pd.concat(reshaped_dfs, ignore_index=True).groupby('Column_A').first().reset_index()
这里用groupby('Column_A').first()是为了处理不同DF中同一Column_A的重复行,确保每个Column_A只保留一行,你也可以根据需求换成sum或mean来聚合数值。
合并后的结果就和你期望的结构完全一致:
| Column_A | Type1 | Type2 | Type3 | Type4 | Type5 | Type6 |
|---|---|---|---|---|---|---|
| a | 100 | 300 | NaN | NaN | NaN | NaN |
| b | NaN | NaN | 356 | 288 | NaN | NaN |
| d | 453 | NaN | NaN | NaN | NaN | NaN |
| m | 100 | NaN | NaN | NaN | 300 | NaN |
| n | NaN | NaN | NaN | NaN | 846 | 356 |
| o | 7455 | NaN | NaN | NaN | NaN | NaN |
步骤3:空值填充
空值填充完全取决于你的业务需求,常见的几种方式:
- 填充固定值(比如0):
filled_df = merged_df.fillna(0)
- 填充列的均值/中位数(适合数值型列):
# 填充均值 filled_df = merged_df.fillna(merged_df.mean(numeric_only=True)) # 填充中位数 filled_df = merged_df.fillna(merged_df.median(numeric_only=True))
- 按
Column_A分组填充组内的均值/中位数:
filled_df = merged_df.groupby('Column_A').transform(lambda x: x.fillna(x.mean()))
- 保留空值(如果后续分析允许NaN存在):直接跳过填充步骤即可。
注意事项
- 如果你的300个DataFrame数据量很大,建议分批次处理,避免内存溢出;
pivot_table的aggfunc参数一定要根据你的业务场景选择,比如如果同一Column_A+CounterName有多条记录,是取第一个、求和还是取平均;- 如果
Column_A的取值存在大小写或格式不一致的情况,建议先统一格式(比如转小写、去除空格)再合并。
内容的提问来源于stack exchange,提问作者Pronomita Dey
相关产品推荐
相关产品推荐

