如何在Polars中将数值列的值添加到对应列表列的每个元素中?
问题
给定如下Polars DataFrame:
import polars as pl df = pl.DataFrame({ 'lst': [[0, 1], [9, 8]], 'val': [3, 4] })
需要将val列的数值添加到lst列对应列表的每个元素中,得到如下结果:
┌───────────┬─────┐ │ lst ┆ val │ │ --- ┆ --- │ │ list[i64] ┆ i64 │ ╞═══════════╪═════╡ │ [3, 4] ┆ 3 │ │ [13, 12] ┆ 4 │ └───────────┴─────┘
已知添加常量值的写法:
new_df = df.with_columns( pl.col('lst').list.eval(pl.element() + 2) )
但尝试以下代码时触发错误:
new_df = df.with_columns( pl.col('lst').list.eval(pl.element() + pl.col('val')) )
错误信息:
polars.exceptions.ComputeError: named columns are not allowed in `list.eval`; consider using `element` or `col("")`
求无需使用map_elements的优雅实现方式。
解决方案
方法1:通过pl.col("")访问当前行外部列
在list.eval的上下文里,无法直接用列名引用外部列,但可以用pl.col("")指代当前行的完整数据,再通过get方法取出val列的值:
new_df = df.with_columns( pl.col('lst').list.eval(pl.element() + pl.col("").get('val')) )
方法2:用list.zip打包后逐元素运算
先把val列按对应lst的长度重复成列表,再和lst打包,最后对每个元素对执行加法:
new_df = df.with_columns( pl.col('lst') .list.zip(pl.col('val').list.repeat_by(pl.col('lst').list.len())) .list.map(lambda x: x[0] + x[1]) )
方法3:结合over子句(Polars 0.19.0+)
如果你的Polars版本≥0.19.0,可以用over将val列的上下文注入list.eval的执行环境:
new_df = df.with_columns( pl.col('lst').list.eval(pl.element() + pl.col('val')).over('val') )
原理说明
list.eval默认的作用域仅局限于列表内部元素,直接引用外部列名会触发作用域错误。pl.col("")可以突破这个限制,获取当前行的所有数据;而over子句则是显式将指定外部列的上下文传入list.eval,让内部可以直接访问该列的值。
内容的提问来源于stack exchange,提问作者barak1412
相关产品推荐
相关产品推荐

