为Polars DataFrame添加多字面量列并垂直扩展的效率问询
关于Polars高效扩展DataFrame并添加indicator列的问题解答
现有方案的效率与内存分析
你的现有方案在内存方面不会重复占用原始DataFrame的内存——Polars默认采用列存储的视图机制,df.with_columns(pl.lit(val))生成的新DataFrame并没有复制原始的group和value列数据,只是在原始列的基础上添加了一个新的常量列,本质上是指向原始数据块的视图。
但在速度方面,如果vals的数量很大(比如成百上千个值),循环生成多个小DataFrame再pl.concat的方式会有额外开销:每次with_columns的轻微成本、多次concat的合并操作,整体效率不如一次完成的向量式操作。
更高效的实现方式
推荐两种Polars原生的高效操作,避免循环和多次concat:
方法1:交叉连接(Cross Join)
创建仅包含indicator列的小型DataFrame,直接和原始DataFrame做交叉连接,一步完成行扩展和列添加:
import polars as pl pl.Config(tbl_rows=-1) df = pl.DataFrame({"group": ["A", "A", "A", "B", "B"], "value": [1, 2, 3, 4, 5]}) vals = [10, 20, 30] # 生成indicator的DataFrame并交叉连接 result = df.join(pl.DataFrame({"indicator": vals}), how="cross") print(result)
输出和你现有方案完全一致,但操作是一次性的,性能更优,尤其当vals数量大时优势明显。
方法2:利用explode扩展行
先给原始DataFrame添加一个包含所有vals的列表列,再通过explode将列表拆分为多行:
result = df.with_columns(indicator=pl.lit(vals)).explode("indicator") print(result)
这种方式代码更简洁,同样是向量式操作,效率远高于循环concat的方式。
总结
- 你的现有方案不会重复占用原始数据的内存,但速度上有优化空间;
- 优先选择交叉连接或explode的方式,这两种都是Polars原生的高效操作,能避免循环带来的额外开销。
内容的提问来源于stack exchange,提问作者Andi
相关产品推荐
相关产品推荐

