如何将嵌套JSON完整展开为Pandas DataFrame?诺贝尔奖API数据处理问题咨询
解决方案:完全展开嵌套JSON到Pandas DataFrame
我明白你想要把所有嵌套层级(包括prizes和里面的affiliations)都展开成单独列,同时保留没有获奖记录的条目。下面是一步步的实用解决方案:
方法1:一次性展开两层嵌套(推荐)
这种方法直接处理laureates→prizes→affiliations的嵌套结构,同时保留所有元数据,还能优雅处理缺失的嵌套字段:
import pandas as pd import requests # 拉取API数据 resp = requests.get('http://api.nobelprize.org/v1/laureate.json') data = resp.json() # 拆分有奖项和无奖项的获奖者,确保无奖项条目不丢失 laureates_with_prizes = [item for item in data['laureates'] if 'prizes' in item and item['prizes']] laureates_without_prizes = [item for item in data['laureates'] if 'prizes' not in item or not item['prizes']] # 处理有奖项的条目:一次性展开prizes和affiliations df_with_prizes = pd.json_normalize( laureates_with_prizes, # 多层record_path指定要展开的嵌套层级 record_path=['prizes', 'affiliations'], # 保留所有需要的元数据,包括获奖者信息和奖项细节 meta=[ 'id', 'firstname', 'surname', 'born', 'died', 'bornCountry', 'bornCountryCode', 'bornCity', 'diedCountry', 'diedCountryCode', 'diedCity', 'gender', ['prizes', 'year'], ['prizes', 'category'], ['prizes', 'share'], ['prizes', 'motivation'] ], # 忽略缺失的嵌套字段(比如没有affiliations的奖项) errors='ignore' ) # 把嵌套的列名(比如('prizes', 'year'))改成更友好的格式 df_with_prizes.columns = [ '_'.join(col) if isinstance(col, tuple) else col for col in df_with_prizes.columns ] # 处理无奖项的条目,直接转为DataFrame df_without_prizes = pd.DataFrame(laureates_without_prizes) # 合并两个数据集,确保所有条目都被保留 df_final = pd.concat([df_with_prizes, df_without_prizes], ignore_index=True, sort=False) # 查看核心字段示例 print(df_final[['id', 'firstname', 'surname', 'prizes_year', 'prizes_category', 'name', 'city']].head(10))
方法2:分步展开(适合理解过程)
如果你想更清晰地看到每一步的展开逻辑,可以分两步处理:
第一步:展开prizes列
# 展开获奖者的奖项,保留基础信息 df_prizes = pd.json_normalize( data['laureates'], record_path='prizes', meta=['id', 'firstname', 'surname', 'born', 'died', 'gender', 'bornCountry'], errors='ignore' )
第二步:展开affiliations列
# 展开每个奖项的附属机构,保留之前的所有列 df_final = pd.json_normalize( df_prizes.to_dict('records'), record_path='affiliations', meta=df_prizes.columns.drop('affiliations').tolist(), errors='ignore' )
关键参数解释
record_path:指定要展开的嵌套列表路径,多层嵌套可以用列表形式(比如['prizes', 'affiliations'])。meta:指定需要保留的非嵌套字段,包括上层的元数据(比如获奖者的姓名、ID)和嵌套层级的其他字段(比如奖项的年份、类别)。errors='ignore':当某个条目没有对应的嵌套字段(比如没有prizes或者没有affiliations)时,不会抛出错误,而是生成空值或保留现有数据。
这样处理后,你就能得到一个完全扁平化的DataFrame,所有嵌套结构都被展开为单独的列,同时没有丢失任何条目。
内容的提问来源于stack exchange,提问作者Shivangi._k




