如何从嵌套的JSON和字典创建Pandas DataFrame

4
我正在尝试从JSON文件创建一个Pandas数据框。我看到了很多解决方案,它们使用了from_dict/json_normalize的内置函数,但是我无法将其应用到我的代码中。这是我的JSON文件中数据的结构:
     "data": [
   {
      "groups": {
         "data": [
               {
               "group": "Math",
               "year_joined": "2009"
               },
               {
               "group_name": "History",
               "year_joined": "2011"
               },
               {
               "group_name": "Biology",
               "year_joined": "2010"
               }
         ]
      },
      "id": "12512"
   },

当我尝试使用pandas函数对这些数据进行归一化时,如下所示:

path = 'mypath'
f = open(path)
data = json.load(f)

test = pd.json_normalize(
            data['data'], 
            errors='ignore') 

我刚刚收到了这样的东西:
    id      groups.data
0   12512   [{'group_name': 'Math', 'year_joined': '2009', 'gr...
1   23172   [{'group_name': 'Chemistry', 'year_joined': '2005'...

我希望这些数据呈现如下(解决方案1):
    id      group     year_joined
0   12512   group1    year1
1   12512   group2    year2
2   12512   group3    year3

或者像这样(解决方案2):

    id      group                   year_joined
0   12512   group1,group2,group3    year1,year2,year3
1   23172   group4,group5           year4,year5

如何实现呢?我尝试将'record_path'参数传递给'json_normalize'函数,但没有任何变化。我还尝试使用'DataFrame.from_dict'函数来解决这个问题,但失败了。我唯一能够找到解决方案1的方法是创建多个循环,遍历json文件中的所有内容,并将其添加到单独的列表中。这种方法有点有效,但在处理大型数据集时需要花费很长时间。
我应该如何使用内置的pandas工具来处理文件,这些文件在上述示例中嵌套为第三层的字典结构?
3个回答

4
  • 假设您有一个具有嵌套列表的字典
    1. 从总体结构创建数据框架
    2. explode() 嵌入式列表
    3. 使用 apply(pd.Series) 扩展嵌套的字典
d = {'groups': {'data': [{'group': 'Math', 'year_joined': '2009'},
   {'group_name': 'History', 'year_joined': '2011'},
   {'group_name': 'Biology', 'year_joined': '2010'}]},
 'id': '12512'}

pd.json_normalize(d).explode("groups.data").reset_index(drop=True).pipe(
    lambda d: d["id"].to_frame().join(d["groups.data"].apply(pd.Series))
)

id 分组 入职年份 组名
0 12512 数学 2009
1 12512 2011 历史
2 12512 2010 生物学

1
你需要从data字典中收集信息。 解决方案1
d = {}
for group in data["data"]:
    groups = [x["group_name"] for x in group['groups']["data"]]
    d['id'] = d.get('id', []) + [group['id']] * len(groups)
    d['group'] = d.get('group', []) + groups
    d['year_joined'] = d.get('year_joined', []) + [x["year_joined"] for x in group['groups']["data"]]

df = pd.DataFrame(d)

输出

      id      group year_joined
0  12512       Math        2009
1  12512    History        2011
2  12512    Biology        2010
3  23172  Chemistry        2007
4  23172  Economics        2008

解决方案2
d = {}
for group in data["data"]:
    d['id'] = d.get('id', []) + [group['id']]
    d['group'] = d.get('group', []) + [','.join(x["group_name"] for x in group['groups']["data"])]
    d['year_joined'] = d.get('year_joined', []) + [','.join(x["year_joined"] for x in group['groups']["data"])]

df = pd.DataFrame(d)

输出

      id                 group     year_joined
0  12512  Math,History,Biology  2009,2011,2010
1  23172   Chemistry,Economics       2007,2008

0

这似乎适用于您的示例:

data = [ # Original data from question
   {
      "groups": {
         "data": [
               {
               "group": "Math",
               "year_joined": "2009"
               },
               {
               "group_name": "History",
               "year_joined": "2011"
               },
               {
               "group_name": "Biology",
               "year_joined": "2010"
               }
         ]
      },
      "id": "12512"
   },
]
# Use the record_path to extract the list we are interested in, and make sure we retain ID
df = pandas.json_normalize(data, record_path=['groups','data'], meta=['id'])
# Combine the group and group_name columns into a single column as they appear mutually exclusive
df["group"] = df["group_name"].fillna(df["group"])
# Discard the now unnecessary column
df.drop(columns='group_name', inplace=True)

它给出:

year_joined group id
0 2009 数学 12512
1 2011 历史 12512
2 2010 生物学 12512

创建第二个数据框:

df.groupby(['id']).agg({'year_joined':list,'group':list})
id year_joined group
12512 ['2009', '2011', '2010'] ['数学', '历史', '生物']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接