You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python读取含字典列的CSV并拆分:为何pd.json_normalize返回空列

问题描述

我有一个名为test.csv的CSV文件,数据如下:

,ts,snapshot
0,1686321823605,"{'asks': [['26566.1', '1.451456']], 'bids': [['26566', '4.17579913']]}"
1,1686321823705,"{'asks': [['26566.1', '1.451456']], 'bids': [['26566', '4.17579913']]}"

用pandas读取的代码:

import pandas as pd
df = pd.read_csv("test.csv")

读取结果:

Unnamed: 0 ts           snapshot    
0           0.0  1686321823605  {'asks': [['26566.1', '1.451456']], 'bids': [[...
1           1.0  1686321823705  {'asks': [['26566.1', '1.451456']], 'bids': [[...

我需要把snapshot列拆分为asks0、asks1、bids0、bids1四列,期望结果:

ts,asks0, asks1, bids0, bids1
1686321823605 , 26566.1 , 1.451456 , 26566 , 4.17579913
1686321823705 , 26566.1 , 1.451456 , 26566 , 4.17579913

尝试用pd.json_normalize()却得到n行×0列的空表:

df1 = pd.json_normalize(df.snapshot)
df1
解决方法

错误原因

pd.json_normalize()只能解析真正的Python字典/列表对象,或者符合JSON规范的字符串(双引号包裹)。但你的snapshot列是单引号格式的字符串,本质还是文本,不是可直接解析的结构化数据,所以无法识别,返回空表。

正确实现代码

推荐用ast.literal_eval解析字符串为字典(比替换引号更可靠,能处理复杂嵌套场景):

import pandas as pd
import ast

# 读取CSV,可选index_col=0去掉Unnamed:0列
df = pd.read_csv("test.csv", index_col=0)

# 将snapshot列的字符串解析为真实字典
df['snapshot'] = df['snapshot'].apply(ast.literal_eval)

# 解析字典列,展开asks和bids字段
normalized_data = pd.json_normalize(df['snapshot'])

# 将asks、bids中的列表拆分为单独列
normalized_data[['asks0', 'asks1']] = pd.DataFrame(normalized_data['asks'].tolist(), index=normalized_data.index)
normalized_data[['bids0', 'bids1']] = pd.DataFrame(normalized_data['bids'].tolist(), index=normalized_data.index)

# 合并ts列与拆分后的列,得到最终结果
final_df = pd.concat([df['ts'], normalized_data[['asks0', 'asks1', 'bids0', 'bids1']]], axis=1)

print(final_df)

如果你的数据里没有嵌套的单引号,也可以用替换引号+json.loads的方式:

import pandas as pd
import json

df = pd.read_csv("test.csv", index_col=0)
# 替换单引号为双引号,转为JSON格式字符串
df['snapshot'] = df['snapshot'].str.replace("'", '"')
# 解析为字典
df['snapshot'] = df['snapshot'].apply(json.loads)

# 后续步骤和上述代码一致
normalized_data = pd.json_normalize(df['snapshot'])
normalized_data[['asks0', 'asks1']] = pd.DataFrame(normalized_data['asks'].tolist(), index=normalized_data.index)
normalized_data[['bids0', 'bids1']] = pd.DataFrame(normalized_data['bids'].tolist(), index=normalized_data.index)
final_df = pd.concat([df['ts'], normalized_data[['asks0', 'asks1', 'bids0', 'bids1']]], axis=1)

print(final_df)

运行后即可得到你期望的列结构。

内容的提问来源于stack exchange,提问作者djg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 05:02:01