如何将Pandas数据帧转换为三级嵌套字典?

2024-05-28 23:53:10 发布

您现在位置:Python中文网/ 问答频道 /正文

如何使用列名将Pandas数据帧转换为三级嵌套字典

列不是前三列,我希望它按列artist分组,然后按列album分组,并且我需要它不区分大小写,最好不使用defaultdict

这是一个最小的可复制示例:

from collections import defaultdict                                               
from itertools import product                                                     
from pandas import DataFrame                                                      
tree = defaultdict(lambda: defaultdict(dict))                                     
columns = {'a': str(), 'b': str(), 'c': str(), 'd': int(), 'e': int(), 'f': int()}
df = DataFrame(columns, index=[])                                                 
for i, j, k in product('abcd', repeat=3):                                         
    tree[i][j][k] = list(map('abcd'.index, (i, j, k)))                            
    df.loc[len(df)] = [i, j, k, *list(map('abcd'.index, (i, j, k)))]              

如何从df获取类似于tree的嵌套字典

我真的很抱歉,我可以提供任何实际的例子,因为它们不是最小的

我试图使用.groupby(),但我只看到它与一列一起使用,我真的不知道如何处理它返回的pandas.core.groupby.generic.DataFrameGroupBy对象,我今天才开始使用它


目前我可以这样做:

tree1 = dict()                                                                                  
for index, row in df.iterrows():                                                                
    if not tree1.get(row['a'].lower()):                                                         
        tree1[row['a'].lower()] = dict()                                                        
    if not tree1[row['a'].lower()].get(row['b'].lower()):                                       
        tree1[row['a'].lower()][row['b'].lower()] = dict()                                      
    tree1[row['a'].lower()][row['b'].lower()][row['c'].lower()] = [row['d'], row['e'], row['f']]

实际上,我实现了不区分大小写的strdict,但是为了简洁起见(它们很长),我不会在这里使用它

但是根据这个答案https://stackoverflow.com/a/55557758/16383578这样的方法是不好的,有什么更好的方法


Tags: fromimporttreedfindex字典lowerdict
1条回答
网友
1楼 · 发布于 2024-05-28 23:53:10

我可能会这样做:

cols = ['a', 'b', 'c']
for col in cols:
    df[col] = df[col].str.casefold()
tree = {}
for (a, b, c), values in (df.set_index(cols).T.to_dict(orient='list')
                            .items()):
    tree.setdefault(a, {}).setdefault(b, {})[c] = values

...
for (a, b, c), values in (df.set_index(cols).apply(list, axis=1)
                            .to_dict()).items():
    tree.setdefault(a, {}).setdefault(b, {})[c] = values

这会产生相同的结果(当包含第一个casefolds零件时)

def to_dict(df):
    return df.set_index(df.columns[0]).iloc[:, 0].to_dict()

df['values'] = df[['d', 'e', 'f']].apply(list, axis=1)
df = df[['a', 'b', 'c', 'values']]
tree = (df.set_index(['a', 'b'])
          .groupby(['a', 'b']).apply(to_dict)
          .reset_index('b')
          .groupby('a').apply(to_dict)
          .to_dict())

但我觉得这有点太复杂了

结果:

{'a': {'a': {'a': [0, 0, 0], 'b': [0, 0, 1], 'c': [0, 0, 2], 'd': [0, 0, 3]},
       'b': {'a': [0, 1, 0], 'b': [0, 1, 1], 'c': [0, 1, 2], 'd': [0, 1, 3]},
       'c': {'a': [0, 2, 0], 'b': [0, 2, 1], 'c': [0, 2, 2], 'd': [0, 2, 3]},
       'd': {'a': [0, 3, 0], 'b': [0, 3, 1], 'c': [0, 3, 2], 'd': [0, 3, 3]}},
 'b': {'a': {'a': [1, 0, 0], 'b': [1, 0, 1], 'c': [1, 0, 2], 'd': [1, 0, 3]},
       'b': {'a': [1, 1, 0], 'b': [1, 1, 1], 'c': [1, 1, 2], 'd': [1, 1, 3]},
       'c': {'a': [1, 2, 0], 'b': [1, 2, 1], 'c': [1, 2, 2], 'd': [1, 2, 3]},
       'd': {'a': [1, 3, 0], 'b': [1, 3, 1], 'c': [1, 3, 2], 'd': [1, 3, 3]}},
 'c': {'a': {'a': [2, 0, 0], 'b': [2, 0, 1], 'c': [2, 0, 2], 'd': [2, 0, 3]},
       'b': {'a': [2, 1, 0], 'b': [2, 1, 1], 'c': [2, 1, 2], 'd': [2, 1, 3]},
       'c': {'a': [2, 2, 0], 'b': [2, 2, 1], 'c': [2, 2, 2], 'd': [2, 2, 3]},
       'd': {'a': [2, 3, 0], 'b': [2, 3, 1], 'c': [2, 3, 2], 'd': [2, 3, 3]}},
 'd': {'a': {'a': [3, 0, 0], 'b': [3, 0, 1], 'c': [3, 0, 2], 'd': [3, 0, 3]},
       'b': {'a': [3, 1, 0], 'b': [3, 1, 1], 'c': [3, 1, 2], 'd': [3, 1, 3]},
       'c': {'a': [3, 2, 0], 'b': [3, 2, 1], 'c': [3, 2, 2], 'd': [3, 2, 3]},
       'd': {'a': [3, 3, 0], 'b': [3, 3, 1], 'c': [3, 3, 2], 'd': [3, 3, 3]}}}

相关问题 更多 >

    热门问题