通过id选择行并计算polar with Rust中的平均值



我有以下数据框和一个名称向量。

<表类> 名称 年龄 tbody><<tr>熊猫5polarbear7海马1

如果您使用特性is_in,则可以直接对存在于另一个Expr中的列进行过滤,这会导致以下结果:

fn main() -> Result<(), PolarsError> {
// Added another panda to see the effect of groupby-mean
let df = df! [
"name" => ["panda", "panda", "polarbear", "seahorse"],
"age" => [5, 55, 7, 1],
]?;
let names = vec!["panda", "seahorse"];
let df = df
.lazy()
.filter(col("name").is_in(lit(Series::from_iter(names))))
.groupby([col("name")])
.agg([col("age").mean()]);
println!("{:?}", df.collect()?);
Ok(())
}
┌──────────┬──────┐
│ name     ┆ age  │
│ ---      ┆ ---  │
│ str      ┆ f64  │
╞══════════╪══════╡
│ panda    ┆ 30.0 │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┤
│ seahorse ┆ 1.0  │
└──────────┴──────┘

我不确定是否有一种直接的方法来过滤您想要的方式。有一种选择是创建一个单独的DataFrame,其中包含要筛选的名称并执行连接:

let filter_df = df! [
"name" => ["panda", "seahorse"]
].unwrap();
let avg = df.lazy()
.join(filter_df.lazy(), [col("name")], [col("name")], JoinType::Inner)
.select([col("age").mean()]);

不清楚您是否想要对此过滤返回的所有年龄执行平均值(这就是您的问题中的表述方式),如果是这种情况,则此代码应该适用于您。这是输出:

Ok(shape: (1, 1)
┌─────┐
│ age │
│ --- │
│ f64 │
╞═════╡
│ 3.0 │
└─────┘)

你的代码使它看起来像你试图计算所有熊猫和所有海马的平均值。如果是这种情况,那么可以使用.groupby().agg()链:

let avg = df.lazy()
.join(names_df.lazy(), [col("name")], [col("name")], JoinType::Inner)
.groupby([col("name")])
.agg([col("age").mean()]);

生产:

Ok(shape: (2, 2)
┌──────────┬─────┐
│ name     ┆ age │
│ ---      ┆ --- │
│ str      ┆ f64 │
╞══════════╪═════╡
│ seahorse ┆ 1.0 │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
│ panda    ┆ 5.0 │
└──────────┴─────┘)

最新更新