如何将含字典与列表的DataFrame列展开为目标结构?
问题与解决方案
问题描述
现有如下结构的初始DataFrame:
| Category | idlist | | -------- | -----------------------------------------------------------------| | new | {100: ['1A', '2B'], 200: ['2A', '3B'], 300: ['3A', '3B', '4B']} | | old | ['99A', '99B'] |
需要将其转换为以下目标结构:
| Category | id | list | | -------- | --- | -------------------- | | new | 100 | ['1A', '2B'] | | new | 200 | ['2A', '3B'] | | new | 300 | ['3A', '3B', '4B'] | | old | -1 | ['99A', '99B'] |
其中new类别的idlist是数字为键、列表为值的字典;old类别仅为列表,无对应id,默认设为-1。同时需要统一处理两类数据,转换前的原始JSON格式如下:
{'new' : {100: ['1-A', '2-B'], 200: ['2-A', '3-B'], 300: ['3-A', '3-B', '4-B']}, 'old' : ['99-A', '99-B']}
解决方案
可以通过两种方式实现转换,均能统一处理字典和列表类型的数据:
方法一:直接从原始JSON构建目标DataFrame
遍历原始JSON的键值对,区分字典和列表类型,分别生成对应数据行后拼接成最终DataFrame。
import pandas as pd raw_json = {'new' : {100: ['1-A', '2-B'], 200: ['2-A', '3-B'], 300: ['3-A', '3-B', '4-B']}, 'old' : ['99-A', '99-B']} data_rows = [] for category, content in raw_json.items(): if isinstance(content, dict): # 处理字典类型:遍历键值对生成多行 for id_num, item_list in content.items(): data_rows.append({ 'Category': category, 'id': id_num, 'list': item_list }) elif isinstance(content, list): # 处理列表类型:添加默认id-1 data_rows.append({ 'Category': category, 'id': -1, 'list': content }) # 转换为目标DataFrame result_df = pd.DataFrame(data_rows) print(result_df)
运行输出:
Category id list 0 new 100 ['1-A', '2-B'] 1 new 200 ['2-A', '3-B'] 2 new 300 ['3-A', '3-B', '4-B'] 3 old -1 ['99-A', '99-B']
方法二:从已有初始DataFrame转换
针对已存在的初始DataFrame,使用apply逐行处理生成展开记录,再合并为新DataFrame。
import pandas as pd # 构造初始DataFrame initial_df = pd.DataFrame({ 'Category': ['new', 'old'], 'idlist': [ {100: ['1A', '2B'], 200: ['2A', '3B'], 300: ['3A', '3B', '4B']}, ['99A', '99B'] ] }) # 定义行处理函数 def expand_row(row): category = row['Category'] content = row['idlist'] output_rows = [] if isinstance(content, dict): for id_num, item_list in content.items(): output_rows.append({ 'Category': category, 'id': id_num, 'list': item_list }) elif isinstance(content, list): output_rows.append({ 'Category': category, 'id': -1, 'list': content }) return pd.DataFrame(output_rows) # 应用函数并合并结果 result_df = pd.concat(initial_df.apply(expand_row, axis=1).tolist(), ignore_index=True) print(result_df)
运行输出:
Category id list 0 new 100 ['1A', '2B'] 1 new 200 ['2A', '3B'] 2 new 300 ['3A', '3B', '4B'] 3 old -1 ['99A', '99B']
核心说明
- 通过
isinstance()判断idlist的类型,精准区分字典和列表进行差异化处理; - 字典类型直接遍历键值对生成多行记录,数字键可直接作为
id列的值,不存在格式问题; - 列表类型生成单条记录,统一设置默认id为-1,实现两类数据的统一转换。
内容的提问来源于stack exchange,提问作者trojan horse
相关产品推荐
相关产品推荐

