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

如何在Polars LazyFrame中执行透视(Pivot)操作?

Polars LazyFrame 实现透视(Pivot)操作的解决方案

问题背景

使用pl.scan_parquet()加载大数据集时,LazyFrame没有内置pivot方法,直接调用会触发AttributeError;且数据集过大无法通过collect()转为DataFrame处理,最终需要将结果通过sink_parquet()保存。

此前尝试用group_by替代时,因pl.col('my_signal').unique()是Polars表达式,无法直接在Python字典推导中迭代,触发TypeError。

可行方案

方案一:先获取唯一信号值再动态生成聚合列

my_signal的唯一值数量通常远小于数据集规模,可安全收集这部分极小数据,再基于唯一值列表构建聚合逻辑:

  1. 获取my_signal的所有唯一值(仅收集极小数据集,无内存压力):
import polars as pl

df = pl.scan_parquet("your_data.parquet")
# 提取唯一信号值转为Python列表
signal_values = df.select(pl.col("my_signal").unique()).collect().to_series().to_list()
  1. 执行分组聚合实现透视效果:
pivoted_df = df.group_by("ind1", "ind2", "ind3", "ind4").agg(
    **{
        signal: pl.col("Value").filter(pl.col("my_signal") == signal).mean()
        for signal in signal_values
    }
)
  1. 保存结果:
pivoted_df.sink_parquet("pivoted_result.parquet")

方案二:使用pl.when()动态生成列(无需提前收集唯一值)

若已知my_signal的取值范围,可直接通过pl.when()为每个信号值生成条件聚合列,全程无需收集数据:

pivoted_df = df.group_by("ind1", "ind2", "ind3", "ind4").agg(
    pl.when(pl.col("my_signal") == "a").then(pl.col("Value")).mean().alias("a"),
    pl.when(pl.col("my_signal") == "b").then(pl.col("Value")).mean().alias("b"),
    pl.when(pl.col("my_signal") == "c").then(pl.col("Value")).mean().alias("c")
)

pivoted_df.sink_parquet("pivoted_result.parquet")

结果验证

以上方案生成的LazyFrame执行后,结果与DataFrame的pivot操作完全一致,示例数据输出如下:

shape: (2, 7)
┌──────┬──────┬──────┬──────┬──────┬─────┬──────┐
│ ind1 ┆ ind2 ┆ ind3 ┆ ind4 ┆ a    ┆ b   ┆ c    │
│ ---  ┆ ---  ┆ ---  ┆ ---  ┆ ---  ┆ --- ┆ ---  │
│ str  ┆ str  ┆ str  ┆ str  ┆ f64  ┆ f64 ┆ f64  │
╞══════╪══════╪══════╪══════╪══════╪═════╪══════╡
│ www  ┆ xxx  ┆ yyy  ┆ zzz  ┆ 1.0  ┆ 2.0 ┆ null │
│ fff  ┆ xxx  ┆ yyy  ┆ zzz  ┆ null ┆ 2.0 ┆ 3.0  │
└──────┴──────┴──────┴──────┴──────┴─────┴──────┘

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 03:05:20