如何展开DataFrame列中的嵌套JSON对象列表并与原表关联
展开DataFrame中嵌套JSON列表并关联原数据的方法
针对你提供的示例数据(tax_info列是字符串格式的嵌套JSON列表),以下是几种实用的处理方法:
前提准备
首先需要将字符串格式的JSON列表转换为Python可识别的列表/字典对象,示例中字符串用单引号,适合用ast.literal_eval解析(比json.loads更适配这种非标准JSON格式):
import pandas as pd import ast # 加载示例数据 data = { 'tax_info': [ '[]', "[{'price': '1.26', 'rate': 0.06, 'title': 'Idaho State Tax', 'price_set': {'shop_money': {'amount': '1.26', 'currency_code': 'USD'}, 'presentment_money': {'amount': '1.26', 'currency_code': 'USD'}}, 'channel_liable': False}]", "[{'price': '1.98', 'rate': 0.0625, 'title': 'Illinois State Tax', 'price_set': {'shop_money': {'amount': '1.98', 'currency_code': 'USD'}, 'presentment_money': {'amount': '1.98', 'currency_code': 'USD'}}, 'channel_liable': False}, {'price': '0.39', 'rate': 0.0125, 'title': 'Chicago City Tax', 'price_set': {'shop_money': {'amount': '0.39', 'currency_code': 'USD'}, 'presentment_money': {'amount': '0.39', 'currency_code': 'USD'}}, 'channel_liable': False}, {'price': '0.87', 'rate': 0.0275, 'title': 'Cook County Tax', 'price_set': {'shop_money': {'amount': '0.87', 'currency_code': 'USD'}, 'presentment_money': {'amount': '0.87', 'currency_code': 'USD'}}, 'channel_liable': False}]", ] } df = pd.DataFrame(data) # 将字符串转为Python对象 df['tax_info'] = df['tax_info'].apply(ast.literal_eval)
方法1:explode + json_normalize(推荐)
这是最简洁通用的方法,先展开列表,再将嵌套字典拆分为列,最后通过索引关联原数据:
# 展开列表,保留原索引(方便后续关联) df_exploded = df.explode('tax_info', ignore_index=False) # 将嵌套字典展开为列,并关联原数据(除tax_info外的其他列) df_final = pd.json_normalize(df_exploded['tax_info'])\ .set_index(df_exploded.index)\ .join(df.drop('tax_info', axis=1)) # 查看结果 print(df_final.head())
说明:
explode('tax_info')将每行的列表元素拆分为单独行,原索引保留,确保能和原数据对应pd.json_normalize自动将嵌套字典(如price_set)展开为带层级的列名(比如price_set.shop_money.amount)set_index+join保证展开后的数据和原DataFrame的其他列正确关联
方法2:列表推导式手动拼接
适合需要自定义处理逻辑的场景,手动遍历每行数据并拼接:
# 初始化空列表存储结果 result_rows = [] for idx, row in df.iterrows(): tax_list = row['tax_info'] # 空列表则保留原行(可根据需求调整,比如跳过) if not tax_list: result_rows.append(row.to_dict()) continue # 遍历每个tax对象,和原行数据合并 for tax in tax_list: merged_row = row.to_dict() merged_row.update(tax) # 移除原tax_info列,换成展开后的字段 del merged_row['tax_info'] result_rows.append(merged_row) # 转换为DataFrame df_final = pd.DataFrame(result_rows)
说明:
- 可以灵活处理空列表、过滤特定tax对象等自定义需求
- 适合数据量不大的场景,数据量较大时效率略低于方法1
方法3:apply结合pd.DataFrame
通过apply将每行的tax列表转为小DataFrame,再合并到原数据:
# 将每行的tax列表转为DataFrame,并添加原索引 df_tax = df['tax_info'].apply(lambda x: pd.DataFrame(x)).reset_index() # 合并原数据和展开后的tax数据 df_final = df_tax.merge(df, on='index').drop('tax_info', axis=1)
说明:
- 逻辑直观,通过
merge关联原索引 - 空列表会生成空的小DataFrame,合并后对应行的tax字段会为NaN,可根据需求用
dropna或填充
注意事项
- 如果原DataFrame有其他列,所有方法都会保留这些列并和展开后的tax数据正确关联
- 空列表处理:
explode后对应行的tax_info会变为NaN,可通过df_exploded.dropna(subset=['tax_info'])移除,或保留根据业务处理 - 嵌套层级更深的JSON:
pd.json_normalize支持record_path和meta参数指定要展开的嵌套路径,可处理更复杂的结构
内容的提问来源于stack exchange,提问作者DevNo
相关产品推荐
相关产品推荐

