Polars中name.map_fields修改struct字段名时命名错误的修复
问题分析与修复方案
你遇到的问题确实源于pl.col(col).name.map_fields(lambda x: f'{col} ({x})')的使用方式。Python闭包采用延迟绑定机制,循环中的lambda表达式不会立即捕获循环变量col的当前值,而是在实际执行时才去读取col的最终值——也就是循环最后一次迭代的'Qty'。这就导致处理Delta列的结构体字段时,错误地使用了Qty作为前缀,最终出现列名混淆的问题。
修复代码(两种可行方案)
方案一:用默认参数捕获当前循环变量值
通过给lambda添加默认参数,强制捕获循环过程中col的当前值,避免延迟绑定的影响:
import polars as pl cols = ['Delta', 'Qty'] metrics = {'CHECK.US': {'Delta': {'ABC': 1, 'DEF': 2}, 'Qty': {'GHIJ': 3, 'TT': 4}}, 'CHECK.NA': {}, 'CHECK.FR': {'Delta': {'QQQ': 7, 'ABC': 6}, 'Qty': {'SS': 9, 'TT': 5}} } df = pl.DataFrame([{col: v.get(col) for col in cols} for v in metrics.values()])\ .insert_column(0, pl.Series('key', metrics.keys()))\ .with_columns([ pl.col(col).name.map_fields(lambda x, col=col: f'{col} ({x})') for col in cols ])
方案二:显式生成字段名映射字典
逐个处理每个结构体列,提前生成字段名的映射关系,逻辑更直观:
import polars as pl cols = ['Delta', 'Qty'] metrics = {'CHECK.US': {'Delta': {'ABC': 1, 'DEF': 2}, 'Qty': {'GHIJ': 3, 'TT': 4}}, 'CHECK.NA': {}, 'CHECK.FR': {'Delta': {'QQQ': 7, 'ABC': 6}, 'Qty': {'SS': 9, 'TT': 5}} } df = pl.DataFrame([{col: v.get(col) for col in cols} for v in metrics.values()])\ .insert_column(0, pl.Series('key', metrics.keys())) for col in cols: # 生成当前结构体字段的新名称映射 field_rename_map = {field: f'{col} ({field})' for field in df.schema[col].names()} df = df.with_columns(pl.col(col).name.map_fields(field_rename_map))
验证效果
执行df.unnest('Delta')后,会正确生成Delta (ABC)、Delta (DEF)、Delta (QQQ)列,完全匹配你期望的输出格式。
内容的提问来源于stack exchange,提问作者Phil-ZXX
相关产品推荐
相关产品推荐

