Python 将具有两个不同级别数据的dataframe转换为嵌套字典
正如标题中提到的,我有两个不同级别的数据,第一个级别是较高级别和较低级别,较高级别的数据有多个来自附在其上的较低数据的记录(即1:n关系)。我将两个数据帧连接在一起,创建了一个包含两个级别数据的数据帧,如下所示:Python 将具有两个不同级别数据的dataframe转换为嵌套字典,python,pandas,dictionary,Python,Pandas,Dictionary,正如标题中提到的,我有两个不同级别的数据,第一个级别是较高级别和较低级别,较高级别的数据有多个来自附在其上的较低数据的记录(即1:n关系)。我将两个数据帧连接在一起,创建了一个包含两个级别数据的数据帧,如下所示: id col1 col2 col3 col4 col5 col6 1 5 10 5 15 9 6 1 5 10 5 14 15 8 2
id col1 col2 col3 col4 col5 col6
1 5 10 5 15 9 6
1 5 10 5 14 15 8
2 8 2 5 6 13 2
2 8 2 5 9 18 6
3 1 4 10 4 5 17
3 1 4 10 9 16 17
前四列(id、col1、col2、col3)与较高级别的数据相关,而后三列(col4、col5和col6)则来自较低级别的数据。这里还可以使用1:n关系,其中前四列在多行上具有相同的值,而后三列具有唯一的值。我想将此数据帧转换为以下格式的python字典:
{
"id": 1,
"data": {
"col1": 5,
"col2": 10,
"col3": 5,
"low_level_data": [
{"col4": 15, "col5": 9, "col6": 6},
{"col4": 14, "col5": 15, "col6": 8}
]
},
"id": 2,
"data": {
"col1": 8,
"col2": 2,
"col3": 5,
"low_level_data": [
{"col4": 6, "col5": 13, "col6": 2},
{"col4": 9, "col5": 18, "col6": 6}
]
},
"id": 3,
"data": {
"col1": 1,
"col2": 4,
"col3": 10,
"lower_level_data": [
{"col4": 4, "col5": 5, "col6": 17},
{"col4": 9, "col5": 16, "col6": 17}
]
}
}
我知道我需要使用to_dict()
方法,但我不确定如何确保输出将非唯一列作为字典中的键,同时在下面级别的列表中也包含较低级别的列。我发现的其他答案似乎没有相同的数据结构,我自己也无法得到想要的输出。我尝试了以下方法,但不幸的是没有给出想要的输出
df.groupby(["id", "col1", "col2", "col3"]).agg(lambda x: x.tolist()).to_dict("index")
# output
{('1', '5', '10', '5'): {'col4': ['15', '14'],
'col5': ['9', '15'],
'col6': ['6', '8']},
('2', '8', '2', '5'): {'col4': ['6', '9'],
'col5': ['13', '18'],
'col6': ['2', '6']},
('3', '1', '4', '10'): {'col4': ['4', '9'],
'col5': ['5', '16'],
'col6': ['17', '17']}}
示例数据帧可按如下方式创建:
data = """id col1 col2 col3 col4 col5 col6
1 5 10 5 15 9 6
1 5 10 5 14 15 8
2 8 2 5 6 13 2
2 8 2 5 9 18 6
3 1 4 10 4 5 17
3 1 4 10 9 16 17"""
data = [x.split("\t") for x in data.split("\n")]
df = pd.DataFrame(data[1:], columns=data[0])
我认为标准的
pandas
方法并不适合这种情况。我只需在data.frame上迭代以构建所需的输出
df.groupby(["id", "col1", "col2", "col3"]).agg(lambda x: x.tolist()).to_dict("index")
# output
{('1', '5', '10', '5'): {'col4': ['15', '14'],
'col5': ['9', '15'],
'col6': ['6', '8']},
('2', '8', '2', '5'): {'col4': ['6', '9'],
'col5': ['13', '18'],
'col6': ['2', '6']},
('3', '1', '4', '10'): {'col4': ['4', '9'],
'col5': ['5', '16'],
'col6': ['17', '17']}}
我想你的输出应该是一个目录,而不是一个目录。以下是解决方案的外观:
result = []
for id in df.id.unique():
tmp_df = df.loc[df.id == id]
tmp_res = {
"id": tmp_df["id"].iloc[0],
"data": {
"col1": tmp_df["col1"].iloc[0],
"col2": tmp_df["col2"].iloc[0],
"col3": tmp_df["col3"].iloc[0],
"low_level_data": tmp_df.loc[:, ["col4", "col5", "col6"]].to_dict("record")
}
}
result.append(tmp_res)
正如Quang和Alex提到的,我提供的预期输出不是有效的python字典,而是字典列表。虽然Alex的答案有效并给出了预期的结果,但我还是设法自己找到了答案,使用了多种
groupby
和apply
方法,我觉得这些方法更灵活一些
(
df
.groupby(["id", "col1", "col2", "col3"])["col4", "col5", "col6"]
.apply(lambda x: x.to_dict("r"))
.rename("low_level_data")
.reset_index()
.groupby("id")["col1", "col2", "col3", "low_level_data"]
.apply(lambda x: x.to_dict("r")[0])
.rename("data")
.reset_index()
.to_dict("r")
)
# output
[{'id': '1',
'data': {'col1': '5',
'col2': '10',
'col3': '5',
'low_level_data': [{'col4': '15', 'col5': '9', 'col6': '6'},
{'col4': '14', 'col5': '15', 'col6': '8'}]}},
{'id': '2',
'data': {'col1': '8',
'col2': '2',
'col3': '5',
'low_level_data': [{'col4': '6', 'col5': '13', 'col6': '2'},
{'col4': '9', 'col5': '18', 'col6': '6'}]}},
{'id': '3',
'data': {'col1': '1',
'col2': '4',
'col3': '10',
'low_level_data': [{'col4': '4', 'col5': '5', 'col6': '17'},
{'col4': '9', 'col5': '16', 'col6': '17'}]}}]
您的预期输出不是有效的Python字典:重复的键
id
,和data
等。