
Polars 中通过 with_columns() 添加新列并非低效的“全量复制”,而是轻量级的元数据指针重组;DataFrame 和 Series 均基于 Apache Arrow 内存模型,实际数据不会被拷贝或移动。
polars 中通过 `with_columns()` 添加新列并非低效的“全量复制”,而是轻量级的元数据指针重组;dataframe 和 series 均基于 apache arrow 内存模型,实际数据不会被拷贝或移动。
在 Polars 中向已有 DataFrame 添加新列(如 new_column)的标准且推荐方式是使用 .with_columns() 方法并重新赋值:
import polars as pl
df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]})
df = df.with_columns(
new_column = pl.lit("static_value"),
computed_col = pl.col("a") * 2,
is_even = (pl.col("a") % 2 == 0)
)这段代码看似“重建”了整个 DataFrame,实则完全无性能负担:Polars 的 DataFrame 是零拷贝(zero-copy)抽象层,其内部由指向底层 Arrow 数组的智能指针构成。调用 .with_columns() 仅创建新的逻辑视图(view),原有列数据内存地址不变,新增列若为常量(pl.lit)或惰性表达式(pl.col(...)),也仅注册计算逻辑,不立即执行或分配新内存。
✅ 正确理解:df = df.with_columns(...) 不等于“深拷贝”,而等价于“添加列定义 + 共享原始数据”。
你可能会看到一些替代写法,例如:
- df.insert_at_idx(i, series) —— 支持按位置插入 Series;
- df.hstack([df, new_series]) —— 水平拼接;
- (不推荐)尝试模拟 pandas 的 inplace=True 风格。
但需明确:
? insert_at_idx() 和 hstack() 在语义和实现上与 with_columns() 本质一致——它们同样不移动原始数据,仅重组列容器结构;
? Polars 没有也不支持真正的 inplace 修改(因违背其不可变计算图设计哲学),所有“修改”均为返回新逻辑 DataFrame;
? with_columns() 是最清晰、最符合 Polars 惯例的 API,支持批量添加、表达式计算、命名赋值,且具备最佳可读性与优化潜力(如查询引擎自动融合表达式)。
? 实践建议:
- 始终优先使用 df = df.with_columns(...),无需顾虑性能损耗;
- 若需动态生成列名,可用字典解包:df = df.with_columns(**{col_name: pl.lit(val) for col_name, val in config.items()});
- 对超大数据集,避免在循环中频繁调用 with_columns()(虽无拷贝,但会累积表达式计划开销),应尽量合并为单次调用;
- 可通过 df.estimated_size() 或 df.n_chunks() 辅助验证数据是否真实复用(添加列前后内存估算值基本不变)。
总之,在 Polars 中,“重赋值”不是妥协,而是高效、安全、可组合的设计体现——拥抱它,而非规避它。










