pd.json_normalize展开嵌套列表列需先explode再normalize,避免直接传入整列导致错乱;apply(pd.Series)适合浅层固定结构;复杂嵌套宜用自定义函数+map处理。

用 pd.json_normalize 展开嵌套列表列(最常用)
当 DataFrame 某列的每个元素是 Python 列表(如 [{"id": 1, "name": "a"}, {"id": 2, "name": "b"}]),且你想把每个字典展开为多行,pd.json_normalize 是最直接的选择。它本质是把“每行一个列表”转成“每字典一行”,并自动处理字段嵌套。
常见错误是直接传入整个列(pd.json_normalize(df["col"])),结果会把整列当做一个 JSON 对象解析,导致结构错乱。正确做法是先用 explode 把列表打散,再对结果列调用 json_normalize:
-
df_exploded = df.explode("col")—— 把嵌套列表列按行展开,空列表变NaN -
normalized = pd.json_normalize(df_exploded["col"])—— 对已展开的单个字典逐行解析 - 最后用
pd.concat([df_exploded.drop("col", axis=1), normalized], axis=1)合并回原表
用 apply(pd.Series) 快速扁平化简单嵌套列表
如果嵌套结构很浅(例如每行是形如 ["a", "b", "c"] 的纯值列表,或固定长度的字典列表如 [{"x": 1}, {"x": 2}]),apply(pd.Series) 更轻量、无需导入额外模块。
但要注意:它会把列表自动对齐成列,缺失位置填 NaN;若列表长度差异大,会产生大量空列,后续需手动清理。性能上比 explode + json_normalize 稍快,但可读性和扩展性差。
立即学习“Python免费学习笔记(深入)”;
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
-
df[["item_0", "item_1", "item_2"]] = df["col"].apply(pd.Series)—— 适合固定长度场景 - 若列表含字典,
pd.Series会把 key 当列名,value 当值,但只展开一层,深层嵌套(如{"meta": {"score": 95}})不会递归解析 - 遇到
None或空列表时返回pd.Series(dtype=object),可能引发ValueError,建议提前用df["col"].fillna([])
处理含混合类型或不规则嵌套时用自定义函数 + map
当列中混有 None、字符串、列表、字典甚至嵌套更深的结构(如 [{"tags": [{"name": "py"}, {"name": "ds"}]}]),json_normalize 和 apply(pd.Series) 都容易报错或产出意外列名。
此时写一个明确的提取函数更可靠,配合 map(比 apply 更快,不推断 dtype)能控制每一步行为:
- 函数内用
isinstance(x, list)判空和类型,用try/except捕获键缺失(如item.get("tags", [])) - 返回统一结构的字典(如
{"tag_name_0": ..., "tag_name_1": ...}),或固定长度列表,避免列数波动 -
df["col_parsed"] = df["col"].map(your_parse_func),再对结果列做apply(pd.Series)或explode
注意 explode 的 dtype 行为和空值陷阱
explode 看似简单,但实际使用中几个细节常被忽略:
- 输入列必须是
object类型;若列被误设为string(比如从 CSV 读入后未处理),explode会把字符串当字符序列拆开,而非按列表解析 - 空列表
[]被explode后变成NaN,不是空行;若想保留空行,需在explode前用df["col"] = df["col"].apply(lambda x: x if x else [None]) -
explode不支持嵌套字典直接展开(如{"items": [...]}),必须先用.str.get("items")或.map(lambda x: x.get("items"))提取列表字段
嵌套越深,越需要分步验证中间结果的 shape 和 dtype——尤其在数据源不可控时,一次 explode 后立刻检查 df_exploded["col"].apply(type).value_counts() 很有必要。

















