我正在尝试创建一个pandas数据帧形式的json文件。我已经看到了这个问题的多种解决方案,其中使用了内置函数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"
},
当我试图用熊猫函数来规范这些数据时,如下所示:
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文件中的所有内容,并将其添加到单独的列表中。它有点工作,但在更大的数据集上需要大量时间。
我如何使用内置的panda工具来处理在文件的第三层嵌套为字典的文件,如上所述?
- 假设您有带有嵌套列表的dict
- 从整体结构创建数据帧
explode()
嵌入列表- 使用
apply(pd.Series)
展开嵌套的dict
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))
)
0 | 12512 | 数学 | td style="text align=right;">12512nan | 2011历史生物 |
您需要从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
这似乎适用于您的示例:
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)
它给出:
加入 | 组id | ||
---|---|---|---|
0 | 2009 | 数学 | 12512 |
1 | 2011 | 历史12512 | |
2 | 2010 | 生物学 | 12512[/tr>