我正在寻找一种将DataFrame转换为嵌套字典的通用方法
这是一个示例数据框
name v1 v2 v3
0 A A1 A11 1
1 A A2 A12 2
2 B B1 B12 3
3 C C1 C11 4
4 B B2 B21 5
5 A A2 A21 6
Run Code Online (Sandbox Code Playgroud)
列数可能不同,列名也可能不同.
像这样 :
{
'A' : {
'A1' : { 'A11' : 1 }
'A2' : { 'A12' : 2 , 'A21' : 6 }} ,
'B' : {
'B1' : { 'B12' : 3 } } ,
'C' : {
'C1' : { 'C11' : 4}}
}
Run Code Online (Sandbox Code Playgroud)
实现这一目标的最佳方法是什么?
我得到的最接近的是该zip功能,但还没有设法使其工作超过一个级别(两列).
DSM*_*DSM 36
我不明白为什么B2你的词典中没有.我也不确定在重复列值的情况下你想要发生什么(除了最后一个,我的意思是每一个.)假设第一个是疏忽,我们可以使用递归:
def recur_dictify(frame):
if len(frame.columns) == 1:
if frame.values.size == 1: return frame.values[0][0]
return frame.values.squeeze()
grouped = frame.groupby(frame.columns[0])
d = {k: recur_dictify(g.ix[:,1:]) for k,g in grouped}
return d
Run Code Online (Sandbox Code Playgroud)
哪个产生
>>> df
name v1 v2 v3
0 A A1 A11 1
1 A A2 A12 2
2 B B1 B12 3
3 C C1 C11 4
4 B B2 B21 5
5 A A2 A21 6
>>> pprint.pprint(recur_dictify(df))
{'A': {'A1': {'A11': 1}, 'A2': {'A12': 2, 'A21': 6}},
'B': {'B1': {'B12': 3}, 'B2': {'B21': 5}},
'C': {'C1': {'C11': 4}}}
Run Code Online (Sandbox Code Playgroud)
但是,使用非熊猫方法可能更简单:
def retro_dictify(frame):
d = {}
for row in frame.values:
here = d
for elem in row[:-2]:
if elem not in here:
here[elem] = {}
here = here[elem]
here[row[-2]] = row[-1]
return d
Run Code Online (Sandbox Code Playgroud)
您可以轻松地重建字典,如下所示
>>> result = {}
>>> for lst in df.values:
... leaf = result
... for path in lst[:-2]:
... leaf = leaf.setdefault(path, {})
... leaf.setdefault(lst[-2], list()).append(lst[-1])
...
>>> result
{'A': {'A1': {'A11': [1]}, 'A2': {'A21': [6], 'A12': [2]}}, 'C': {'C1': {'C11': [4]}}, 'B': {'B1': {'B12': [3]}, 'B2': {'B21': [5]}}}
Run Code Online (Sandbox Code Playgroud)
如果您确定您的叶子不会重叠,请替换最后一行
... leaf.setdefault(lst[-2], list()).append(lst[-1])
Run Code Online (Sandbox Code Playgroud)
同
... leaf[lst[-2]] = lst[-1]
Run Code Online (Sandbox Code Playgroud)
得到你想要的输出:
>>> result
{'A': {'A1': {'A11': 1}, 'A2': {'A21': 6, 'A12': 2}}, 'C': {'C1': {'C11': 4}}, 'B': {'B1': {'B12': 3}, 'B2': {'B21': 5}}}
Run Code Online (Sandbox Code Playgroud)
用于测试的示例数据:
import pandas as pd
data = {'name': ['A','A','B','C','B','A'],
'v1': ['A1','A2','B1','C1','B2','A2'],
'v2': ['A11','A12','B12','C11','B21','A21'],
'v3': [1,2,3,4,5,6]}
df = pd.DataFrame.from_dict(data)
Run Code Online (Sandbox Code Playgroud)