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
相关产品推荐
相关产品推荐

