Pandas合并DataFrame后合并C/D列替换NaT,能否在合并时处理?
我在对两个DataFrame进行左连接后得到了如下DataFrame:
A B C_x D_x C_y D_y 0 1136006640 NaT NaT 2022-11-18 2022-11-24 1 1136030941 NaT NaT 2022-11-30 2022-12-09 3 1136051543 2022-11-25 2022-12-16 NaT NaT 4 1136072241 NaT NaT 2022-12-20 2022-12-29 其中C_x与C_y、D_x与D_y始终是一方有数据另一方为NaT,我想要合并C_x和C_y为C列、D_x和D_y为D列,用非NaT值填充对应位置的NaT,请问能否在合并阶段完成该操作,还是必须在合并后再处理?
嗨,我来帮你解决这个问题~先给你明确答案:两种方式都能实现,不过如果想一步到位,在合并的链式操作里完成是完全可行的,能省掉单独处理的步骤,下面给你详细说两种方法:
方法1:合并阶段(链式操作)完成
这种方法把合并和列合并放在同一段代码里,不需要单独写后续处理逻辑,相当于“合并阶段”完成全部操作。核心用combine_first()方法,它会优先取第一个列的非缺失值,如果是NaT就自动取第二个列的值,完美匹配你的需求。
假设你原来的左连接代码是用pd.merge(),可以改成这样:
import pandas as pd # 假设你的两个原始DataFrame是df1和df2 merged_clean_df = ( pd.merge(df1, df2, on=["A", "B"], how="left") # 合并C_x/C_y为C列,D_x/D_y为D列 .assign( C=lambda df: df["C_x"].combine_first(df["C_y"]), D=lambda df: df["D_x"].combine_first(df["D_y"]) ) # 删除多余的_x/_y列 .drop(columns=["C_x", "C_y", "D_x", "D_y"]) )
运行后直接得到你想要的结果:
| A | B | C | D |
|---|---|---|---|
| 0 | 1136006640 | 2022-11-18 | 2022-11-24 |
| 1 | 1136030941 | 2022-11-30 | 2022-12-09 |
| 3 | 1136051543 | 2022-11-25 | 2022-12-16 |
| 4 | 1136072241 | 2022-12-20 | 2022-12-29 |
方法2:合并后再处理
如果你已经得到了带_x/_y后缀的中间DataFrame,也可以单独做列合并处理,逻辑和上面一致:
# 假设你已经有了合并后的merged_df merged_df["C"] = merged_df["C_x"].combine_first(merged_df["C_y"]) merged_df["D"] = merged_df["D_x"].combine_first(merged_df["D_y"]) # 删除多余列 merged_df = merged_df.drop(columns=["C_x", "C_y", "D_x", "D_y"])
两种方法效果完全相同,选哪种看你的代码习惯:如果想代码更紧凑、少写中间变量,选方法1;如果需要先查看合并后的中间结果再处理,选方法2。
另外补充个小技巧:因为你说C_x/C_y、D_x/D_y始终是一方有值一方为NaT,用fillna()也能实现,比如merged_df["C"] = merged_df["C_x"].fillna(merged_df["C_y"]),效果和combine_first()一样,但combine_first()更通用——如果偶尔出现两边都有值的情况,它会优先保留左连接左边(_x)的值,更符合左连接的逻辑。
内容的提问来源于stack exchange,提问作者Petra Enis

