如何原地修改Polars DataFrame中的嵌套数组列
嘿,我来帮你搞定Polars里修改嵌套数组列的问题~首先得先说明白:Polars这个库的设计思路是**不可变(immutable)**的,也就是说它本身就不推荐“原地修改”DataFrame,这种设计能避免很多意外的bug,让数据处理更安全。不过咱们可以用它推荐的方式,实现看起来像“原地更新”的效果,而且更符合Polars的用法。
先把你给的示例DataFrame补全(刚才的代码最后有点小问题,我帮你修正了):
import polars as pl df = pl.DataFrame( { "points": [ [[1.0, 2.0]], [[3.0, 4.0], [5.0, 6.0]], [[7.0, 8.0], [9.0, 10.0], [11.0, 12.0]] ] } )
接下来给你两种常用的修改方式,按需选就行:
1. 用Polars原生数组操作(推荐,速度快)
如果你的修改逻辑是比较规则的(比如给每个点的坐标做加减乘除、修改某个位置的元素),用Polars自带的数组操作方法最靠谱,因为是库内部优化过的,速度比自定义Python函数快很多。
比如我想把每个点的x坐标乘2,y坐标加3,代码可以这么写:
# 生成新的DataFrame并重新赋值给df,看起来就像原地更新了 df = df.with_columns( pl.col("points").arr.eval( # 针对最内层的每个点(比如[1.0,2.0])做修改 pl.element().list.set(0, pl.element()[0] * 2) # 修改第0位(x坐标) .list.set(1, pl.element()[1] + 3), # 修改第1位(y坐标) recursive=True # 深入到最内层的数组(每个二维点) ) )
运行之后,df["points"]里的每个点就都被修改了,比如原来的[[1.0,2.0]]会变成[[2.0,5.0]]。
如果只是简单的添加/删除元素,比如给每个points数组末尾加一个[0.0,0.0],直接用arr.append更简单:
df = df.with_columns( pl.col("points").arr.append([0.0, 0.0]) )
2. 自定义Python函数修改(适合复杂逻辑)
如果你的修改逻辑特别复杂,Polars原生方法搞不定,那就用map_elements调用自定义函数。比如我想把每个points数组里的点都倒序排列:
# 先写好自定义的修改函数 def reverse_points(arr): # arr是每个行对应的嵌套数组,比如[[3.0,4.0],[5.0,6.0]] return arr[::-1] # 用map_elements修改列,然后重新赋值 df = df.with_columns( pl.col("points").map_elements( reverse_points, return_dtype=pl.List(pl.List(pl.Float64)) # 要指定返回的类型,避免Polars自动推断出错 ) )
不过要注意,map_elements是调用Python函数,速度会比原生方法慢,数据量大的时候尽量用第一种方法。
最后再啰嗦一句:虽然咱们说“原地修改”,但本质上Polars是生成了一个新的DataFrame对象,然后把原来的df变量指向这个新对象——这是Polars设计的最优解,比强行原地修改更安全。
备注:内容来源于stack exchange,提问作者DJDuque

