如何定位两个Polars DataFrame之间的差异?
定位Polars DataFrame差异的方法
针对你的需求,以下是高效定位并标记/过滤差异行的方案,适配多列场景:
1. 先关联两个DataFrame(你已完成此步骤)
import polars as pl df1 = pl.DataFrame([ {'id': 1,'col1': ['a',None],'col2': ['x']}, {'id': 2,'col1': ['b'],'col2': ['y', None]}, {'id': 3,'col1': [None],'col2': ['z']}] ) df2 = pl.DataFrame([ {'id': 1,'col1': ['a'],'col2': ['x']}, {'id': 2,'col1': ['b', None],'col2': ['y', None]}, {'id': 3,'col1': [None],'col2': ['z']}] ) # 按id关联,添加后缀区分两个DataFrame的列 joined_df = df1.join(df2, on='id', suffix='_df2')
2. 自动生成差异判断逻辑
因为实际列数多,我们可以通过列名自动匹配需要对比的列对,避免手动逐个编写:
# 获取除id外的所有原列 original_cols = [col for col in df1.columns if col != 'id'] # 生成每列的差异判断条件:原列 vs df2对应列 diff_conditions = [pl.col(col) != pl.col(f"{col}_df2") for col in original_cols]
3. 方案一:添加布尔列标记差异行
给每行添加has_difference列,标记该行是否存在任意列差异:
result_with_flag = joined_df.with_columns( has_difference=pl.any_horizontal(diff_conditions) )
输出结果:
┌─────┬─────────────┬─────────────┬─────────────┬─────────────┬───────────────┐ │ id ┆ col1 ┆ col2 ┆ col1_df2 ┆ col2_df2 ┆ has_difference│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ list[str] ┆ list[str] ┆ list[str] ┆ list[str] ┆ bool │ ╞═════╪═════════════╪═════════════╪═════════════╪═════════════╪═══════════════╡ │ 1 ┆ ["a", null] ┆ ["x"] ┆ ["a"] ┆ ["x"] ┆ true │ │ 2 ┆ ["b"] ┆ ["y", null] ┆ ["b", null] ┆ ["y", null] ┆ true │ │ 3 ┆ [null] ┆ ["z"] ┆ [null] ┆ ["z"] ┆ false │ └─────┴─────────────┴─────────────┴─────────────┴─────────────┴───────────────┘
4. 方案二:直接过滤出差异行
仅保留存在差异的行:
diff_rows = joined_df.filter(pl.any_horizontal(diff_conditions))
输出结果:
┌─────┬─────────────┬─────────────┬─────────────┬─────────────┐ │ id ┆ col1 ┆ col2 ┆ col1_df2 ┆ col2_df2 │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ list[str] ┆ list[str] ┆ list[str] ┆ list[str] │ ╞═════╪═════════════╪═════════════╪═════════════╪═════════════╡ │ 1 ┆ ["a", null] ┆ ["x"] ┆ ["a"] ┆ ["x"] │ │ 2 ┆ ["b"] ┆ ["y", null] ┆ ["b", null] ┆ ["y", null] │ └─────┴─────────────┴─────────────┴─────────────┴─────────────┘
进阶:标记具体差异列
如果需要知道每行具体哪些列有差异,可以给每个列添加单独的差异标记:
result_with_col_flags = joined_df.with_columns( # 为每个列添加差异标记列 **{f"{col}_diff": pl.col(col) != pl.col(f"{col}_df2") for col in original_cols}, # 整体差异标记 has_difference=pl.any_horizontal(diff_conditions) )
输出结果:
┌─────┬─────────────┬─────────────┬─────────────┬─────────────┬──────────┬──────────┬───────────────┐ │ id ┆ col1 ┆ col2 ┆ col1_df2 ┆ col2_df2 ┆ col1_diff┆ col2_diff┆ has_difference│ │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ list[str] ┆ list[str] ┆ list[str] ┆ list[str] ┆ bool ┆ bool ┆ bool │ ╞═════╪═════════════╪═════════════╪═════════════╪═════════════╪══════════╪══════════╪═══════════════╡ │ 1 ┆ ["a", null] ┆ ["x"] ┆ ["a"] ┆ ["x"] ┆ true ┆ false ┆ true │ │ 2 ┆ ["b"] ┆ ["y", null] ┆ ["b", null] ┆ ["y", null] ┆ true ┆ false ┆ true │ │ 3 ┆ [null] ┆ ["z"] ┆ [null] ┆ ["z"] ┆ false ┆ false ┆ false │ └─────┴─────────────┴─────────────┴─────────────┴─────────────┴──────────┴──────────┴───────────────┘
说明
- Polars中列表类型的
!=比较是整体匹配:只有两个列表的元素、长度、null位置完全一致时才会返回False,否则返回True,正好适配你的示例场景。 - 自动匹配列对的逻辑无需修改代码即可适配任意数量的列,适合你的实际多列数据。
内容的提问来源于stack exchange,提问作者Luca
相关产品推荐
相关产品推荐

