Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pandas multi index dataframe to nested dictionary

Tags:

pandas

Let's say I have the following dataframe

df = pd.DataFrame({0: {('A', 'a'): 1, ('A', 'b'): 6, ('B', 'a'): 2, ('B', 'b'): 7},
 1: {('A', 'a'): 2, ('A', 'b'): 7, ('B', 'a'): 3, ('B', 'b'): 8},
 2: {('A', 'a'): 3, ('A', 'b'): 8, ('B', 'a'): 4, ('B', 'b'): 9},
 3: {('A', 'a'): 4, ('A', 'b'): 9, ('B', 'a'): 5, ('B', 'b'): 1},
 4: {('A', 'a'): 5, ('A', 'b'): 1, ('B', 'a'): 6, ('B', 'b'): 2}})

which looks this:

     0  1  2  3  4
A a  1  2  3  4  5
  b  6  7  8  9  1
B a  2  3  4  5  6
  b  7  8  9  1  2

When I convert this to a dictionary via to_dict (regardless of stacking, unstacking), I get a dictionary whose keys are tuples:

df.transpose().to_dict()

{('A', 'a'): {0: 1, 1: 2, 2: 3, 3: 4, 4: 5},
 ('A', 'b'): {0: 6, 1: 7, 2: 8, 3: 9, 4: 1},
 ('B', 'a'): {0: 2, 1: 3, 2: 4, 3: 5, 4: 6},
 ('B', 'b'): {0: 7, 1: 8, 2: 9, 3: 1, 4: 2}}

What I'd like instead is a nested dict like this:

{'A':{'a': {0: 1, 1:2, 2:3, 3:4, 4:5}, 'b':{0:6, 1:7, 2:8, 3:9,4:1}...
like image 681
parasu Avatar asked Feb 10 '17 03:02

parasu


2 Answers

You can use a dictionary comprehension to iterate through the outer levels (values 'A' and 'B') and use the xs method to slice the frame by those levels.

{level: df.xs(level).to_dict('index') for level in df.index.levels[0]}

{'A': {'a': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5},
  'b': {0: 6, 1: 7, 2: 8, 3: 9, 4: 1}},
 'B': {'a': {0: 2, 1: 3, 2: 4, 3: 5, 4: 6},
  'b': {0: 7, 1: 8, 2: 9, 3: 1, 4: 2}}}
like image 82
Ted Petrou Avatar answered Nov 10 '22 11:11

Ted Petrou


For n levels you could have something recursive like this:

def createDictFromPandas(df):
    if (df.index.nlevels==1):
        return df.to_dict()
    dict_f = {}
    for level in df.index.levels[0]:
        if (level in df.index):
            dict_f[level] = createDictFromPandas(df.xs([level]))
    return dict_f
like image 33
Bernat Esquirol Avatar answered Nov 10 '22 12:11

Bernat Esquirol