如何用Polars将字典格式字符串列拆分为多列?
问题分析与解决方案
报错原因解析
apply(ast.literal_eval)报错原因:
Polars的apply是逐行执行的Python UDF,本身效率极低,且若ast.literal_eval解析后的字典存在隐性类型不一致(比如某键的值多数是整数,但个别行是字符串格式的数字),Polars因无法统一列类型,会抛出ComputeError: got mixed dtypes while constructing List Series。ndjson相关报错原因:
read_json直接加载3.2GB数据导致服务器崩溃,是因为它会一次性将全量数据载入内存,触发内存不足。scan_ndjson报错是因为你的数据并非标准ndjson格式(每行一个JSON对象),而是CSV字符串字段存储JSON,扫描时识别到的是字符串而非JSON对象,触发类型不匹配错误。
Polars正确实现方法
方法1:内置JSON解析+结构体展开(推荐,性能最优)
用Polars原生矢量化函数解析JSON字符串为结构体,再展开成多列,完全绕开Python UDF的性能瓶颈:
import polars as pl # 读取CSV,保留_source为字符串类型 df = pl.read_csv("your_file.csv") # 1. 将字符串解析为Polars结构体(Struct) df = df.with_columns( pl.col("_source").str.json_parse().alias("source_struct") ) # 2. 展开结构体为独立列,同时移除原_source列 df = df.drop("_source").unnest("source_struct")
若存在少量类型不一致的情况,可手动指定结构体类型强制统一:
# 假设_source字典的键为id、name、score,对应类型分别为整数、字符串、浮点数 struct_schema = pl.Struct({ "id": pl.Int64, "name": pl.Utf8, "score": pl.Float64 }) df = pl.read_csv("your_file.csv").with_columns( pl.col("_source").str.json_parse().cast(struct_schema).alias("source_struct") ).unnest("source_struct")
方法2:转标准ndjson流式处理(适合重复使用场景)
先将CSV中的_source字段提取为标准ndjson格式,再用流式API处理避免内存过载:
import polars as pl # 流式读取CSV,仅提取_source列并输出为ndjson ( pl.scan_csv("your_file.csv") .select("_source") .write_ndjson("converted.ndjson") ) # 流式读取ndjson并加载为DataFrame df = pl.scan_ndjson("converted.ndjson").collect()
性能优化提示
- 永远优先使用Polars的矢量化函数(如
str.json_parse)替代Python UDF(apply),后者会完全绕开Polars的优化引擎,性能暴跌。 - 大文件处理必须用流式API(
scan_csv/scan_ndjson),分块加载数据,避免一次性占用大量内存。
内容的提问来源于stack exchange,提问作者ashtonjesse
相关产品推荐
相关产品推荐

