合并列名部分不同的DataFrame时如何保留原始数据类型?
合并列名部分不同的DataFrame时如何保留原始数据类型?
我太懂你这种困扰了——合并列名不全一致的DataFrame时,原本好好的整数类型突然变成float,后续处理全是坑!下面给你几个高效的解决方案,顺便解答你提到的几个疑问:
一、最简洁的方案:用dtype_backend='numpy_nullable'(Pandas 1.4+支持)
这是Pandas后来推出的特性,专门用来解决缺失值导致的类型转换问题。它会使用Nullable数据类型(比如Int64带空值的整数类型、boolean带空值的布尔类型),既保留原始类型,又能优雅处理缺失值。
代码示例:
import pandas as pd df1 = pd.DataFrame([(2, 3, True, "Test")], columns=["x", "y", "z", "a"]) df2 = pd.DataFrame([(4, 6)], columns=["x", "b"]) # 关键就是加上dtype_backend参数 df3 = pd.concat([df1, df2], ignore_index=True, dtype_backend='numpy_nullable')
处理后你会发现:
x、y列依然是整数类型(Int64),缺失值用pd.NA表示,不会转成float- 布尔、字符串类型也会保留对应的Nullable类型,完美适配你的需求
二、兼容旧版Pandas的方案:先补全列再合并
如果你用的是Pandas 1.4之前的版本,可以先统一所有DataFrame的列,给缺失的列填充对应类型的空值,再执行合并:
import pandas as pd df1 = pd.DataFrame([(2, 3, True, "Test")], columns=["x", "y", "z", "a"]) df2 = pd.DataFrame([(4, 6)], columns=["x", "b"]) # 第一步:收集所有出现过的列名 all_columns = list(set(df1.columns).union(df2.columns)) # 第二步:给每个DataFrame补全缺失的列,填充对应类型的空值 def fill_missing_cols(df, all_cols): for col in all_cols: if col not in df.columns: # 先确定该列的原始数据类型 if col in df1.columns: dtype = df1[col].dtype else: dtype = df2[col].dtype # 根据类型填充对应的空值 if dtype == 'int64': df[col] = pd.NA # 保留整数类型的空值,也可以填0(看你的业务需求) elif dtype == 'float64': df[col] = pd.NA elif dtype == 'bool': df[col] = pd.NA elif dtype == 'object': # 字符串类型 df[col] = "" # 统一列的顺序,避免合并后列乱序 return df[all_cols] # 补全两个DataFrame的列 df1_filled = fill_missing_cols(df1, all_columns) df2_filled = fill_missing_cols(df2, all_columns) # 最后合并 df3 = pd.concat([df1_filled, df2_filled], ignore_index=True)
这个方法虽然代码多一点,但兼容性好,而且完全由你控制缺失值的填充逻辑。
关于你提到的两个疑问解答
1. convert_dtypes()的RuntimeWarning能不能忽略?
可以忽略!这个警告是因为Pandas会尝试把所有列都检查一遍能不能转成整数,而你的布尔、字符串列肯定转不了,所以才会报这个错。它不会影响最终的类型转换结果,只是有点烦人。如果不想看到警告,可以临时屏蔽:
import warnings warnings.filterwarnings("ignore", category=RuntimeWarning) df3 = pd.concat([df1, df2], ignore_index=True).convert_dtypes()
不过还是更推荐前面的dtype_backend方案,更干净高效。
2. 关于FutureWarning的问题
这个警告是Pandas在提示未来版本的合并逻辑会有变化——现在合并时会自动排除全NA/空列,但未来不会。如果你没有全NA的列,或者需要保留所有列的信息,完全不用管这个警告;如果担心,可以在合并前手动过滤掉全NA的列(但你的场景里应该不需要)。
你之前手动添加空行再逐个填值的方法虽然可行,但数据量大的时候效率确实低,上面的两种方法都能帮你节省大量时间~
备注:内容来源于stack exchange,提问作者ACM
相关产品推荐
相关产品推荐

