如何在Polars中将结构体列展开为行
如何在Polars中将结构体列展开为行
看起来你想要把每个结构体里的字段转成单独的行,同时保留各个地区的数值对应关系对吧?这确实不能直接用unnest或explode搞定,得结合几个Polars的操作来实现,我给你一步步拆解:
首先先回顾下你的原始数据:
import polars as pl df = pl.DataFrame({'EU': {'size': 10, 'GDP': 80}, 'US': {'size': 100, 'GDP': 800}, 'AS': {'size': 80, 'GDP': 500}})
原始输出是:
shape: (1, 3) ┌───────────┬───────────┬───────────┐ │ EU ┆ US ┆ AS │ │ --- ┆ --- ┆ --- │ │ struct[2] ┆ struct[2] ┆ struct[2] │ ╞═══════════╪═══════════╪═══════════╡ │ {10,80} ┆ {100,800} ┆ {80,500} │ └───────────┴───────────┴───────────┘
方法一:转置+展开+透视组合操作
result = ( df # 先转置,把地区列变成行,原来的struct列变成新的"value"列 .transpose(include_header=True, header_name="region") # 展开struct列,得到size和GDP两个数值列 .unnest("value") # 把size/GDP列转成行,生成记录类型的metric列和对应数值 .melt(id_vars="region", variable_name="metric", value_name="value") # 透视回目标结构:以metric为行,地区为列填充数值 .pivot(index="metric", columns="region", values="value") # 调整列顺序,让metric列排在最前面 .select(["metric", "EU", "US", "AS"]) ) print(result)
运行后就能得到你想要的结果:
shape: (2, 4) ┌────────┬─────┬─────┬─────┐ │ metric ┆ EU ┆ US ┆ AS │ │ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ i64 ┆ i64 ┆ i64 │ ╞════════╪═════╪═════╪═════╡ │ size ┆ 10 ┆ 100 ┆ 80 │ │ GDP ┆ 80 ┆ 800 ┆ 500 │ └────────┴─────┴─────┴─────┘
步骤细节解释
.transpose(...):把原DataFrame的行列互换,让原来的地区列名(EU/US/AS)变成新的region列,struct值统一放到value列,此时数据是3行2列的结构。.unnest("value"):把嵌套的struct列拆成单独的数值列,现在数据变成3行3列(region、size、GDP)。.melt(...):将宽表转成窄表,把size和GDP这两个数值列转成metric标记行,同时保留对应的数值和地区信息,此时数据是6行3列。.pivot(...):把窄表转回宽表,以metric为行索引,地区为列,填充对应数值,得到目标的2行4列结构。.select(...):最后调整列的顺序,让metric列处于第一列,符合你的预期格式。
如果你想要封装成类似你设想的expand_structs函数,也可以自己实现:
def expand_structs(df, metric_col_name="metric"): return ( df .transpose(include_header=True, header_name="region") .unnest("value") .melt(id_vars="region", variable_name=metric_col_name, value_name="value") .pivot(index=metric_col_name, columns="region", values="value") .select([metric_col_name] + df.columns) ) # 调用函数 result = expand_structs(df) print(result)
这样调用起来就和你设想的用法差不多啦!
备注:内容来源于stack exchange,提问作者Phil-ZXX
相关产品推荐
相关产品推荐

