Как переключить структуру вложенности словаря словарей в Python

#python

#python #словарь #вложенный

Вопрос:

Если у меня есть следующий словарь:

 dict_a = {'a': {'x': 0, 'y': 1, 'z': 2},
          'b': {'x': 3, 'y': 4, 'z': 5}}
 

Каков наилучший способ переключить структуру словаря на:

 dict_b = {'x': {'a': 0, 'b': 3},
          'y': {'a': 1, 'b': 4},
          'z': {'a': 2, 'b': 5}}
 

Комментарии:

1. Лучше уточнить, нужно ли вам обрабатывать несоответствующие данные.

2. Всегда ли словарь имеет глубину в два уровня ?

3. Да, всегда два уровня

Ответ №1:

Со словарем по умолчанию

Учитывая, что словарь всегда имеет глубину в два уровня, вы можете сделать это с помощью defaultdict :

 from collections import defaultdict

dict_b = defaultdict(dict)

for k,v in dict_a.items():
    for k2,v2 in v.items():
        dict_b[k2][k] = v2 

Что дает:

 >>> dict_b
defaultdict(<class 'dict'>, {'x': {'a': 0, 'b': 3}, 'z': {'a': 2, 'b': 5}, 'y': {'a': 1, 'b': 4}})
>>> dict(dict_b)
{'x': {'a': 0, 'b': 3}, 'z': {'a': 2, 'b': 5}, 'y': {'a': 1, 'b': 4}}
 

defaultdict является подклассом dict , вы можете снова превратить результат в ванильный dict с dict_b = dict(dict_b) помощью (как показано во втором запросе).

С pandas

Вы также можете использовать pandas для этого:

 from pandas import DataFrame

dict_b = DataFrame(dict_a).transpose().to_dict() 

Это дает:

 >>> DataFrame(dict_a).transpose().to_dict()
{'y': {'a': 1, 'b': 4}, 'x': {'a': 0, 'b': 3}, 'z': {'a': 2, 'b': 5}}
 

Ответ №2:

Нам не нужно defaultdict переносить вложенный dict, если мы используем setdefault :

 def transpose(nested_dict):
    result = dict()

    for x, nested in nested_dict.items():
        for a, val in nested.items():
            result.setdefault(a, dict())[x] = val

    return result