如何用Polars地道合并行与列均重叠的DataFrame?
用Polars实现带优先级的DataFrame合并(行/列均重叠场景)
问题背景
有两个DataFrame,共享标识列i,其余列存在重叠(如a)和独有列(如b、c),行和列都有部分重叠,示例代码如下:
import polars as pl df = pl.DataFrame( { "i": [1, 2, 3, 4], "a": [2.6, 5.3, None, None], "b": ["ab", "cd", "ef", "gh"] } ) df2 = pl.DataFrame( { "i": [2, 3, 5, 6], "a": [None, 3.5, 2.5, 0.9], "c": [True, False, False, True] } )
现有方法存在的局限:
- 对角线拼接+
unique()会丢失独有的列数据(如i=2的c列值) - 全外连接后手动合并重叠列(如
a和a_right),列数多时操作繁琐 - 将重叠列加入
on参数会导致同一i但值不同/缺失的行无法合并
期望合并结果:保留每个标识的所有已知数据,可指定单元格的数据源优先级(如优先保留某DataFrame的非空值),最终输出如下:
┌─────┬──────┬──────┬───────┐ │ i ┆ a ┆ b ┆ c │ │ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ f64 ┆ str ┆ bool │ ╞═════╪══════╪══════╪═══════╡ │ 2 ┆ 5.3 ┆ cd ┆ true │ │ 3 ┆ 3.5 ┆ ef ┆ false │ │ 5 ┆ 2.5 ┆ null ┆ false │ │ 6 ┆ 0.9 ┆ null ┆ true │ │ 1 ┆ 2.6 ┆ ab ┆ null │ │ 4 ┆ null ┆ gh ┆ null │ └─────┴──────┴──────┴───────┘
解决方案
通过全外连接+自动合并重叠列的方式实现,可灵活指定数据源优先级:
import polars as pl # 定义原始DataFrame df = pl.DataFrame( { "i": [1, 2, 3, 4], "a": [2.6, 5.3, None, None], "b": ["ab", "cd", "ef", "gh"] } ) df2 = pl.DataFrame( { "i": [2, 3, 5, 6], "a": [None, 3.5, 2.5, 0.9], "c": [True, False, False, True] } ) # 1. 执行全外连接,保留所有行和列,对右表重叠列添加后缀 joined_df = df.join(df2, on="i", how="full", suffix="_right") # 2. 自动识别并合并重叠列 # 获取除标识列外的重叠列名 overlap_columns = [col for col in df.columns if col in df2.columns and col != "i"] for col in overlap_columns: # 用coalesce指定优先级:优先取左表(df)的非空值,左表为空则取右表(df2)的值 # 若要优先右表,调换coalesce内的列顺序即可 joined_df = joined_df.with_columns( pl.coalesce([pl.col(col), pl.col(f"{col}_right")]).alias(col) ).drop(f"{col}_right") # 3. 调整列顺序(可选,匹配期望结果) final_result = joined_df.select(["i", "a", "b", "c"]) print(final_result)
关键说明
pl.coalesce():按传入顺序取第一个非空值,通过调整列顺序即可轻松指定数据源优先级- 自动遍历重叠列:避免手动处理大量重叠列的繁琐操作
- 全外连接确保所有行(包括仅在某一个DataFrame中存在的
i)都被保留
补充说明
已在GitHub提交issue,建议添加df.supplement()方法,与df.update()互补,优先保留原DataFrame的非空值,仅补充原DataFrame缺失的值并添加新列。
内容的提问来源于stack exchange,提问作者matterhorn103
相关产品推荐
相关产品推荐

