如何在Rust中获取Polars DataFrame的差异(通用方法)
获取Polars DataFrame过滤前后的差异行
问题场景
你有如下Polars代码,通过过滤得到新的DataFrame,想要获取被过滤移除的行,且希望用通用方法而非反转原过滤条件:
use polars::prelude::*; fn main() -> PolarsResult<()> { let df = df! ( "nrs" => &[Some(1), Some(2), Some(3), Some(4), Some(5)], "names" => &[Some("foo"), Some("ham"), Some("spam"), Some("eggs"), None], "groups" => &["A", "A", "B", "C", "B"], )?; println!("{:?}", df); let df2 = df.lazy().filter(col("nrs").lt(lit(4))).collect()?; println!("{:?}", df2); Ok(()) }
运行输出:
shape: (5, 3) ┌─────┬───────┬────────┐ │ nrs ┆ names ┆ groups │ │ --- ┆ --- ┆ --- │ │ i32 ┆ str ┆ str │ ╞═════╪═══════╪════════╡ │ 1 ┆ foo ┆ A │ │ 2 ┆ ham ┆ A │ │ 3 ┆ spam ┆ B │ │ 4 ┆ eggs ┆ C │ │ 5 ┆ null ┆ B │ └─────┴───────┴────────┘ shape: (3, 3) ┌─────┬───────┬────────┐ │ nrs ┆ names ┆ groups │ │ --- ┆ --- ┆ --- │ │ i32 ┆ str ┆ str │ ╞═════╪═══════╪════════╡ │ 1 ┆ foo ┆ A │ │ 2 ┆ ham ┆ A │ │ 3 ┆ spam ┆ B │ └─────┴───────┴────────┘
解决方案:使用anti_join操作
Polars的anti_join方法可以直接返回左表中不存在于右表的行,完美满足需求,且不需要反转原过滤条件。
修改后的代码如下:
use polars::prelude::*; fn main() -> PolarsResult<()> { let df = df! ( "nrs" => &[Some(1), Some(2), Some(3), Some(4), Some(5)], "names" => &[Some("foo"), Some("ham"), Some("spam"), Some("eggs"), None], "groups" => &["A", "A", "B", "C", "B"], )?; println!("原DataFrame:\n{:?}", df); let df2 = df.lazy().filter(col("nrs").lt(lit(4))).collect()?; println!("过滤后的DataFrame:\n{:?}", df2); // 获取被过滤移除的行:原表anti_join过滤后的表 let removed_rows = df.anti_join(&df2, ["nrs", "names", "groups"])?; println!("被移除的行:\n{:?}", removed_rows); Ok(()) }
运行输出新增部分:
被移除的行: shape: (2, 3) ┌─────┬───────┬────────┐ │ nrs ┆ names ┆ groups │ │ --- ┆ --- ┆ --- │ │ i32 ┆ str ┆ str │ ╞═════╪═══════╪════════╡ │ 4 ┆ eggs ┆ C │ │ 5 ┆ null ┆ B │ └─────┴───────┴────────┘
方法说明
anti_join的核心逻辑是:保留左表(原DataFrame)中未在右表(过滤后的DataFrame)找到匹配的所有行,完全对应你要的“被过滤移除的行”。- 第二个参数是用于匹配的列列表,这里用全部列确保行的完全匹配;如果你的DataFrame有唯一主键列,仅指定该列会更高效。
- 这个方法的通用性极强:无论原过滤条件是简单的数值比较还是复杂的多条件组合,都不需要手动反转逻辑,直接通过表之间的关联就能得到差异。
内容的提问来源于stack exchange,提问作者JACK M
相关产品推荐
相关产品推荐

