如何高效用Pandas json_normalize处理嵌套JSON?报错求助
问题:Pandas json_normalize处理嵌套JSON时多record_path报错的高效解决方法
我尝试用Pandas DataFrame的json_normalize函数规范化深度嵌套的JSON文件,但无法设置多个record_path,尝试时会触发错误,仅设置单个record_path时可成功运行。我尝试逐个规范化所需元素,但认为存在更高效的实现方式,无需逐个处理再拼接。
触发错误的代码
import pandas as pd import json with open('PZZA.json') as f: data = json.load(f) # 规范化数据 df1 = pd.json_normalize(data, record_path=['chart', 'result'], errors='ignore') # 尝试批量规范化嵌套字段 df_nested = pd.json_normalize( df1['indicators.quote'][0], record_path=['open', 'close', 'high', 'low', 'volume'], record_prefix='quote_' )
报错信息
TypeError: 'float' object is not subscriptable
目前只能用的低效写法
df1 = pd.json_normalize(data, record_path=['chart', 'result'], errors = 'ignore') df2 = pd.json_normalize(df1['indicators.quote'][0], record_path=['open']) df3 = pd.json_normalize(df1['indicators.quote'][0], record_path=['close']) df4 = pd.json_normalize(df1['indicators.quote'][0], record_path=['high']) df5 = pd.json_normalize(df1['indicators.quote'][0], record_path=['low']) df6 = pd.json_normalize(df1['indicators.quote'][0], record_path=['volume'])
JSON结构片段说明
- 规范化
result路径后的结构:
{'result': [{'meta': {'currency': 'USD', 'symbol': 'PZZA', 'exchangeName': 'NMS', 'instrumentType': 'EQUITY', 'firstTradeDate': 739546200, 'regularMarketTime': 1626120001, 'gmtoffset': -14400, 'timezone': 'EDT', 'exchangeTimezoneName': 'America/New_York', 'regularMarketPrice': 110.1, 'chartPreviousClose': 1.944, 'priceHint': 2, 'currentTradingPeriod': {'pre': {'timezone': 'EDT', 'start': 1626076800, 'end': 1626096600, 'gmtoffset': -14400}, 'regular': {'timezone': 'EDT', 'start': 1626096600, 'end': 1626120000, 'gmtoffset': -14400}, 'post': {'timezone': 'EDT', 'start': 1626120000,
- 需要提取的
indicators.quote字段结构:
'indicators': {'quote': [{'close': [1.9444444179534912, 2.194444417953491, 2.1111111640930176, 2.25, 2.3333332538604736, 2.2083332538604736, 2.305555582046509, 2.305555582046509, 2.25, 2.25, 2.222222328186035,
解决方案
错误原因
json_normalize的record_path参数是用来指定嵌套记录列表的层级路径,不是多个字段名。当你传入['open', 'close']时,函数会先定位到open对应的列表,然后尝试从open的每个元素(float类型)中提取close字段,这就触发了'float' object is not subscriptable错误。
高效实现方式
因为quote下的open、close、high、low、volume都是长度相同的数值列表,直接用pd.DataFrame构造即可,无需多次调用json_normalize:
import pandas as pd import json with open('PZZA.json') as f: data = json.load(f) # 直接从原始数据提取quote数据构造DataFrame quote_data = data['chart']['result'][0]['indicators']['quote'][0] df_quote = pd.DataFrame({ 'open': quote_data['open'], 'close': quote_data['close'], 'high': quote_data['high'], 'low': quote_data['low'], 'volume': quote_data['volume'] }) # 如果需要和meta数据合并(将meta信息重复对应每一行quote数据) meta_data = data['chart']['result'][0]['meta'] df_meta = pd.DataFrame([meta_data] * len(df_quote)) final_df = pd.concat([df_meta, df_quote], axis=1)
优势
- 一次生成目标DataFrame,避免多次
json_normalize的冗余操作 - 代码更简洁,执行效率更高
- 直接利用列表转DataFrame的特性,匹配当前数据结构的实际情况
内容的提问来源于stack exchange,提问作者xoxo
相关产品推荐
相关产品推荐

