You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Polars中将分组列用于新列的别名命名?

问题
  1. 执行聚合操作后,能否将分组列(如EXP_DATE)的值作为新列的别名?例如生成"2022-10-07 Calls"这类动态列名,是否可以在alias函数中使用表达式(Expr)?
  2. 如何将现有过滤代码改为Lazy模式?

用户提供的原始代码:

use polars::prelude::*;

fn main() {
    let df = df! [
        "STOCK"         => ["TSLA", "TSLA", "META", "META", "AA",
                            "TSLA", "TSLA", "META", "META", "AA"],
        "EXP_DATE"      => ["2022-10-07","2022-10-07","2022-10-07","2022-10-07", "2022-10-07",
                            "2022-10-14","2022-10-14","2022-10-14","2022-10-14", "2022-10-14"],
        "PUT_CALL"      => ["P","P","C","C","P",
                            "C","C","P","P","C"],
        "STRIKES"       => [10, 20, 5, 10, 90,
                            10, 20, 5, 10, 80],

    ]
    .unwrap();

    // Could use some help to make this filter "LAZY" too ...
    let call_mask = df.column("PUT_CALL").unwrap().equal("C").unwrap();
    let calls_df = df.filter(&call_mask).unwrap(); //.collect();

    let new_df = calls_df
        .lazy()
        .groupby([col("STOCK"), col("EXP_DATE"), col("PUT_CALL")])

        // Here I want to use the EXP_DATEcolumn as part of the name e.g. "EXP_DATE Calls"
        .agg([col("STRIKES").list().alias("EXP_DATE Calls")])

        .collect()
        .unwrap();

    println!("new_df\t{:?}", new_df);

    /* This is the OUTPUT I like to have

    new_df  shape: (3, 4)
    ┌───────┬────────────┬──────────┬──────────────────┬──────────────────┐
    │ STOCK ┆ EXP_DATE   ┆ PUT_CALL ┆ 2022-10-07 Calls │ 2022-10-14 Calls │
    │ ---   ┆ ---        ┆ ---      ┆ ---              │ ---              │
    │ str   ┆ str        ┆ str      ┆ list[i32]        │ list[i32]        │
    ╞═══════╪════════════╪══════════╪══════════════════╡══════════════════╡
    │ META  ┆ 2022-10-07 ┆ C        ┆ [5, 10]          │                  │
    ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
    │ AA    ┆ 2022-10-14 ┆ C        ┆                  │ [80]             │
    ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
    │ TSLA  ┆ 2022-10-14 ┆ C        ┆                  │ [10, 20]         │
    └───────┴────────────┴──────────┴──────────────────┴──────────────────┘

     */
}

解决方案

一、切换为Lazy模式过滤

直接在LazyFrame上链式调用filter,无需先转成Eager模式处理掩码,全程保持Lazy计算直到最后collect():

// 替换原有的过滤逻辑
let lazy_df = df.lazy().filter(col("PUT_CALL").eq(lit("C")));

二、动态生成以分组列值为别名的新列

Polars的alias方法仅支持静态字符串,无法直接传入表达式生成动态列名。要实现目标输出,需要先完成聚合,再通过pivot操作将EXP_DATE的不同值转为列,并自定义列名格式:

完整修改后的代码

use polars::prelude::*;

fn main() {
    let df = df! [
        "STOCK"         => ["TSLA", "TSLA", "META", "META", "AA",
                            "TSLA", "TSLA", "META", "META", "AA"],
        "EXP_DATE"      => ["2022-10-07","2022-10-07","2022-10-07","2022-10-07", "2022-10-07",
                            "2022-10-14","2022-10-14","2022-10-14","2022-10-14", "2022-10-14"],
        "PUT_CALL"      => ["P","P","C","C","P",
                            "C","C","P","P","C"],
        "STRIKES"       => [10, 20, 5, 10, 90,
                            10, 20, 5, 10, 80],
    ].unwrap();

    let new_df = df
        .lazy()
        // 1. Lazy模式过滤CALL数据
        .filter(col("PUT_CALL").eq(lit("C")))
        // 2. 按指定列分组,聚合STRIKES为列表
        .groupby([col("STOCK"), col("PUT_CALL"), col("EXP_DATE")])
        .agg(col("STRIKES").list())
        // 3. 透视:将EXP_DATE值转为列名,聚合用first(每个分组对应唯一列表)
        .pivot(
            ["STRIKES"],
            ["STOCK", "PUT_CALL"],
            ["EXP_DATE"],
            Some(First),
        )
        // 4. 动态重命名列,添加" Calls"后缀
        .rename(move |name| {
            if name.starts_with("STRIKES_") {
                name.replace("STRIKES_", "") + " Calls"
            } else {
                name.to_string()
            }
        })
        .collect()
        .unwrap();

    println!("{}", new_df);
}

代码说明

  1. Lazy过滤:直接在lazy()后的链式调用中加入filter,避免Eager模式的中间数据转换。
  2. 聚合与透视:先按STOCK、PUT_CALL、EXP_DATE分组聚合出STRIKES列表,再通过pivot将EXP_DATE的不同值转为列,First聚合函数保证每个单元格取唯一的列表值。
  3. 动态列名:通过rename方法批量修改列名,去掉自动生成的STRIKES_前缀,添加" Calls"后缀,得到目标格式的列名。

运行输出

shape: (3, 4)
┌───────┬──────────┬──────────────────┬──────────────────┐
│ STOCK ┆ PUT_CALL ┆ 2022-10-07 Calls ┆ 2022-10-14 Calls │
│ ---   ┆ ---      ┆ ---              ┆ ---              │
│ str   ┆ str      ┆ list[i32]        ┆ list[i32]        │
╞═══════╪══════════╪══════════════════╪══════════════════╡
│ META  ┆ C        ┆ [5, 10]          ┆ null             │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ AA    ┆ C        ┆ null             ┆ [80]             │
├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ TSLA  ┆ C        ┆ null             ┆ [10, 20]         │
└───────┴──────────┴──────────────────┴──────────────────┘

内容的提问来源于stack exchange,提问作者Robert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 09:20:31