如何基于另一列访问Polars中struct列的指定字段?
在Polars中根据另一列的值动态访问Struct列的字段
你有一个包含Struct列my_struct和字段名列field_name的DataFrame,想要根据field_name每行的值动态提取my_struct对应的字段,但直接使用pl.col("my_struct").struct.field(pl.col("field_name"))会触发TypeError,因为struct.field()只接受字符串字面量,不支持表达式输入。
解决方案1:使用case_when(推荐,高效向量化操作)
通过条件判断匹配field_name的值,对应提取Struct的字段,这种方式是向量化操作,性能远高于逐行处理:
import polars as pl data = {'my_struct': [{'field1': 1, 'field2': 'A'}, {'field1': 2, 'field2': 'B'}], 'field_name': ['field1', 'field2']} df = pl.DataFrame(data) result = df.with_columns( pl.case_when( pl.col("field_name") == "field1", pl.col("my_struct").struct.field("field1"), pl.col("field_name") == "field2", pl.col("my_struct").struct.field("field2") ).alias("selected_field") ) print(result)
输出结果:
shape: (2, 3) ┌───────────┬────────────┬───────────────┐ │ my_struct ┆ field_name ┆ selected_field│ │ --- ┆ --- ┆ --- │ │ struct[2] ┆ str ┆ object │ ╞═══════════╪════════════╪═══════════════╡ │ {1,"A"} ┆ field1 ┆ 1 │ │ {2,"B"} ┆ field2 ┆ B │ └───────────┴────────────┴───────────────┘
解决方案2:动态生成条件表达式(适合大量字段的场景)
如果Struct有很多字段,手动写每个条件太繁琐,可以自动获取Struct的所有字段,动态构造case_when的条件:
struct_fields = df.schema["my_struct"].names result = df.with_columns( pl.case_when( *[(pl.col("field_name") == field, pl.col("my_struct").struct.field(field)) for field in struct_fields] ).alias("selected_field") )
解决方案3:使用map_elements(适合字段极多或快速验证场景)
如果不想处理条件构造,可以用逐行映射的方式,但这种方式性能较低,不建议处理大型数据集:
result = df.with_columns( pl.struct("my_struct", "field_name").map_elements( lambda x: x["my_struct"][x["field_name"]], return_dtype=pl.Object # 若所有字段类型统一,可指定具体类型如pl.Int64/pl.Utf8 ).alias("selected_field") )
为什么原代码报错?
pl.col("my_struct").struct.field()方法的参数要求是固定字符串,用于指定要提取的Struct字段名,无法接收表达式(Expr对象)作为输入,因此直接传入pl.col("field_name")会触发类型错误。
内容的提问来源于stack exchange,提问作者linus heinz
相关产品推荐
相关产品推荐

