Search code examples
pythonpandasdictionarygroup-by

Reorganize nested `dict`


This question is connected to [-> here].
I would like to reorganize the following nested dict please:

a = {
 (0.0, 0.0): {'a': [25, 29, nan]},
 (0.0, 2.0): {'a': [25, 29, nan], 'b': [25, 35, 31.0]},
 (0.0, 4.0): {'b': [25, 35, 31.0]},
 (2.0, 0.0): {'a': [25, 29, nan], 'c': [25, 26, 29.0]},
 (2.0, 1.5): {'a': [25, 29, nan], 'c': [25, 26, 29.0]},
 (2.0, 2.0): {'a': [25, 29, nan], 'b': [25, 35, 31.0]},
 (2.0, 4.0): {'b': [25, 35, 31.0]},
 (3.0, 3.0): {'d': [25, 31, 32.0]},
 (3.0, 5.0): {'d': [25, 31, 32.0]},
 (5.0, 0.0): {'c': [25, 26, 29.0]},
 (5.0, 1.5): {'c': [25, 26, 29.0]},
 (5.0, 3.0): {'d': [25, 31, 32.0]},
 (5.0, 5.0): {'d': [25, 31, 32.0]},
 (6.0, 1.0): {'e': [25, 28, 30.0]},
 (6.0, 3.0): {'e': [25, 28, 30.0]},
 (8.0, 1.0): {'e': [25, 28, 30.0]},
 (8.0, 3.0): {'e': [25, 28, 30.0]}
}

I want to swap the inner and outer keys.
Some outer keys will duplicate and the value should become a list of lists. The result should be:

{'a': {(0.0, 0.0): [[25, 29, nan]],
       (0.0, 2.0): [[25, 29, nan], [25, 35, 31.0]],
       (2.0, 0.0): [[25, 29, nan], [25, 26, 29.0]],
       (2.0, 1.5): [[25, 29, nan], [25, 26, 29.0]],
       (2.0, 2.0): [[25, 29, nan], [25, 35, 31.0]]},
 'b': {(0.0, 2.0): [[25, 29, nan], [25, 35, 31.0]],
       (0.0, 4.0): [[25, 35, 31.0]],
       (2.0, 2.0): [[25, 29, nan], [25, 35, 31.0]],
       (2.0, 4.0): [[25, 35, 31.0]]},
 'c': {(2.0, 0.0): [[25, 29, nan], [25, 26, 29.0]],
       (2.0, 1.5): [[25, 29, nan], [25, 26, 29.0]],
       (5.0, 0.0): [[25, 26, 29.0]],
       (5.0, 1.5): [[25, 26, 29.0]]},
 'd': {(3.0, 3.0): [[25, 31, 32.0]],
       (3.0, 5.0): [[25, 31, 32.0]],
       (5.0, 3.0): [[25, 31, 32.0]],
       (5.0, 5.0): [[25, 31, 32.0]]},
 'e': {(6.0, 1.0): [[25, 28, 30.0]],
       (6.0, 3.0): [[25, 28, 30.0]],
       (8.0, 1.0): [[25, 28, 30.0]],
       (8.0, 3.0): [[25, 28, 30.0]]}
}

Intuition tells me pd.DataFrame with a .groupby() [and cull the NaN cells] would be the way to go...

df = pd.DataFrame(dict_vertices)
print(df.head(2))
             0.0               2.0                    ...  8.0       6.0
             0.0               0.0               1.5  ...  1.0  3.0  3.0
a  [25, 29, nan]     [25, 29, nan]     [25, 29, nan]  ...  NaN  NaN  NaN
c            NaN  [[25, 26, 29.0]]  [[25, 26, 29.0]]  ...  NaN  NaN  NaN

[2 rows x 17 columns]

...but I don't know.
How do I reorganize the following nested dict please; where the value follows the outer key?


Solution

  • You can use:

    out = {}
    
    for k1, d in a.items():
        for k2 in d:
            out.setdefault(k2, {})[k1] = list(d.values())
    

    Output:

    {'a': {(0.0, 0.0): [[25, 29, nan]],
           (0.0, 2.0): [[25, 29, nan], [[25, 35, 31.0]]],
           (2.0, 0.0): [[25, 29, nan], [[25, 26, 29.0]]],
           (2.0, 1.5): [[25, 29, nan], [[25, 26, 29.0]]],
           (2.0, 2.0): [[25, 29, nan], [[25, 35, 31.0]]]},
     'b': {(0.0, 2.0): [[25, 29, nan], [[25, 35, 31.0]]],
           (0.0, 4.0): [[25, 35, 31.0]],
           (2.0, 2.0): [[25, 29, nan], [[25, 35, 31.0]]],
           (2.0, 4.0): [[25, 35, 31.0]]},
     'c': {(2.0, 0.0): [[25, 29, nan], [[25, 26, 29.0]]],
           (2.0, 1.5): [[25, 29, nan], [[25, 26, 29.0]]],
           (5.0, 0.0): [[25, 26, 29.0]],
           (5.0, 1.5): [[25, 26, 29.0]]},
     'd': {(3.0, 3.0): [[25, 31, 32.0]],
           (3.0, 5.0): [[25, 31, 32.0]], 
           (5.0, 3.0): [[25, 31, 32.0]],
           (5.0, 5.0): [[25, 31, 32.0]]},
     'e': {(6.0, 1.0): [[25, 28, 30.0]],
           (6.0, 3.0): [[25, 28, 30.0]],
           (8.0, 1.0): [[25, 28, 30.0]],
           (8.0, 3.0): [[25, 28, 30.0]]},
    }