在循环中创建不同长度的字典以附加到列表中。 (json 到 Pandas 数据帧)
Create dictionaries of varying lengths in loop to append to a list. (json to Pandas DataFrame)
我正在 python 进行分析。我在 json 中收到了 post 请求的响应,我想将一些信息提取到 DataFrame 中,以便在进行一些分析之前与另一个数据帧合并。
json 的形式为:
json = {'type': 'abc',
'results': [{'users': [{'id': '1',
'score': 0.9},
{'id': '2',
'score': 0.2}],
'num_users': 2,
'name': 'john smith'},
{'users': [{'id': '3',
'score': 0.7}],
'num_users': 1,
'name': 'david jones'},
{'users': [{'id': '5',
'score': 0.8},
{'id': '6',
'score': 0.3}],
'num_users': 2,
'name': 'jane smith'}]}
在上面的示例中,我想提取名称及其相关联的 ID 和分数:
name
id_1
score_1
id_2
score_2
John Smith
1
0.9
2
0.2
David Jones
3
0.7
Jane Smith
5
0.8
6
0.3
我最初的计划是在创建数据框之前循环并创建字典列表,但是当我这样做时,我意识到用户数量和分数各不相同,最初认为它应该有 2 个 ID 和分数每个名字。
scores = []
for i in range(0, len(json):
scores.append({'name':json[i]['name'],
'id_1': json[i]['users'][0]['id'],
'score_1': json[i]['users'][0]['score'],
'id_2': json[i]['users'][1]['id'],
'score_2': json[i]['users'][1]['score']})
pd.DataFrame(scores)
如何根据长度创建具有不同长度和键以及不同键名(_1、_2 等)的字典?当变长字典列表传递给 pd.DataFrame 时,这会起作用吗?
谢谢。
如果 data
是你从问题中得到的字典:
df = pd.DataFrame(
[
{"name": d["name"]}
| {
f"{k}_{i}": v
for i, d in enumerate(d["users"], 1)
for k, v in d.items()
}
for d in data["results"]
]
).fillna("")
print(df.to_markdown())
打印:
name
id_1
score_1
id_2
score_2
0
john smith
1
0.9
2
0.2
1
david jones
3
0.7
2
jane smith
5
0.8
6
0.3
或使用 **
而不是 dict | dict
:
df = pd.DataFrame(
[
{
"name": d["name"],
**{
f"{k}_{i}": v
for i, d in enumerate(d["users"], 1)
for k, v in d.items()
},
}
for d in data["results"]
]
).fillna("")
您可以快速使用:
>>> pd.json_normalize(json['results'], 'users', 'name')
id score name
0 1 0.9 john smith
1 2 0.2 john smith
2 3 0.7 david jones
3 5 0.8 jane smith
4 6 0.3 jane smith
然后旋转你的数据框:
out = (pd.json_normalize(json['results'], 'users', 'name')
.assign(colid=lambda x: x.groupby('name')['id'].cumcount().add(1).astype(str))
.pivot('name', 'colid'))
out.columns = out.columns.to_flat_index().map('_'.join).rename(None)
print(out)
# Output
id_1 id_2 score_1 score_2
name
david jones 3 NaN 0.7 NaN
jane smith 5 6 0.8 0.3
john smith 1 2 0.9 0.2
您可以使用 json_normalize
然后 pivot
:
#get the data you need into a dataframe
df = pd.json_normalize(json["results"],record_path="users",meta="name")
#create a counter to pivot
df["counter"] = df.groupby("name").cumcount().add(1)
#pivot to the desired structure
output = df.pivot("name","counter",["id","score"]).sort_values(by="counter",axis=1).rename_axis(None)
#collapse multi-level header to single level
output.columns = output.columns.map("{0[0]}_{0[1]}".format)
>>> output
id_1 score_1 id_2 score_2
david jones 3 0.7 NaN NaN
jane smith 5 0.8 6 0.3
john smith 1 0.9 2 0.2
我正在 python 进行分析。我在 json 中收到了 post 请求的响应,我想将一些信息提取到 DataFrame 中,以便在进行一些分析之前与另一个数据帧合并。
json 的形式为:
json = {'type': 'abc',
'results': [{'users': [{'id': '1',
'score': 0.9},
{'id': '2',
'score': 0.2}],
'num_users': 2,
'name': 'john smith'},
{'users': [{'id': '3',
'score': 0.7}],
'num_users': 1,
'name': 'david jones'},
{'users': [{'id': '5',
'score': 0.8},
{'id': '6',
'score': 0.3}],
'num_users': 2,
'name': 'jane smith'}]}
在上面的示例中,我想提取名称及其相关联的 ID 和分数:
name | id_1 | score_1 | id_2 | score_2 |
---|---|---|---|---|
John Smith | 1 | 0.9 | 2 | 0.2 |
David Jones | 3 | 0.7 | ||
Jane Smith | 5 | 0.8 | 6 | 0.3 |
我最初的计划是在创建数据框之前循环并创建字典列表,但是当我这样做时,我意识到用户数量和分数各不相同,最初认为它应该有 2 个 ID 和分数每个名字。
scores = []
for i in range(0, len(json):
scores.append({'name':json[i]['name'],
'id_1': json[i]['users'][0]['id'],
'score_1': json[i]['users'][0]['score'],
'id_2': json[i]['users'][1]['id'],
'score_2': json[i]['users'][1]['score']})
pd.DataFrame(scores)
如何根据长度创建具有不同长度和键以及不同键名(_1、_2 等)的字典?当变长字典列表传递给 pd.DataFrame 时,这会起作用吗?
谢谢。
如果 data
是你从问题中得到的字典:
df = pd.DataFrame(
[
{"name": d["name"]}
| {
f"{k}_{i}": v
for i, d in enumerate(d["users"], 1)
for k, v in d.items()
}
for d in data["results"]
]
).fillna("")
print(df.to_markdown())
打印:
name | id_1 | score_1 | id_2 | score_2 | |
---|---|---|---|---|---|
0 | john smith | 1 | 0.9 | 2 | 0.2 |
1 | david jones | 3 | 0.7 | ||
2 | jane smith | 5 | 0.8 | 6 | 0.3 |
或使用 **
而不是 dict | dict
:
df = pd.DataFrame(
[
{
"name": d["name"],
**{
f"{k}_{i}": v
for i, d in enumerate(d["users"], 1)
for k, v in d.items()
},
}
for d in data["results"]
]
).fillna("")
您可以快速使用:
>>> pd.json_normalize(json['results'], 'users', 'name')
id score name
0 1 0.9 john smith
1 2 0.2 john smith
2 3 0.7 david jones
3 5 0.8 jane smith
4 6 0.3 jane smith
然后旋转你的数据框:
out = (pd.json_normalize(json['results'], 'users', 'name')
.assign(colid=lambda x: x.groupby('name')['id'].cumcount().add(1).astype(str))
.pivot('name', 'colid'))
out.columns = out.columns.to_flat_index().map('_'.join).rename(None)
print(out)
# Output
id_1 id_2 score_1 score_2
name
david jones 3 NaN 0.7 NaN
jane smith 5 6 0.8 0.3
john smith 1 2 0.9 0.2
您可以使用 json_normalize
然后 pivot
:
#get the data you need into a dataframe
df = pd.json_normalize(json["results"],record_path="users",meta="name")
#create a counter to pivot
df["counter"] = df.groupby("name").cumcount().add(1)
#pivot to the desired structure
output = df.pivot("name","counter",["id","score"]).sort_values(by="counter",axis=1).rename_axis(None)
#collapse multi-level header to single level
output.columns = output.columns.map("{0[0]}_{0[1]}".format)
>>> output
id_1 score_1 id_2 score_2
david jones 3 0.7 NaN NaN
jane smith 5 0.8 6 0.3
john smith 1 0.9 2 0.2