How to do untangle nested dictionary with list in key/value into columns? I tried different combination to solve converting nested dictionary into pandas data frame. Looked through the stack I am getting close to fix the problem just not quite.
Sample Data:
test = {
'abc': {
'company_id': '123c',
'names': ['Oscar', 'John Smith', 'Smith, John'],
'education': ['MS', 'BS']
},
'DEF': {
'company_id': '124b',
'names': ['Matt B.'],
'education': ['']
}
}
Tried:
1)
pd.DataFrame(list(test.items())) # not working entirely - creates {dictionary in col '1'}
2)
df = pd.concat({
k: pd.DataFrame.from_dict(v, 'index') for k, v in test.items()
},
axis=0)
df2 = df.T
df2.reset_index() # creates multiple columns
Output Needed:
With the release of pandas 0.25
and the addition of explode
this is now a lot easier:
frame = pd.DataFrame(test).T
frame = frame.explode('names').set_index(
['company_id', 'names'],
append=True).explode(
'education').reset_index(
['company_id', 'names']
)
This is not really lean but then this is a rather complicated transformation.
Inspired by this blog post, I solved it using two separate iterations of turning the list column into a series and then transforming the DataFrame using melt
.
import pandas as pd
test = {
'abc': {
'company_id': '123c',
'names': ['Oscar', 'John Smith', 'Smith, John'],
'education': ['MS', 'BS']
},
'DEF': {
'company_id': '124b',
'names': ['Matt B.'],
'education': ['']
}
}
frame = pd.DataFrame(test).T
names = frame.names.apply(pd.Series)
frame = frame.merge(
names, left_index=True, right_index=True).drop('names', axis=1)
frame = frame.reset_index().melt(
id_vars=['index', 'company_id', 'education'],
value_name='names').drop('variable', axis=1).dropna()
education = frame.education.apply(pd.Series)
frame = frame.merge(
education, left_index=True, right_index=True).drop('education', axis=1)
frame = frame.melt(
id_vars=['index', 'company_id', 'names'],
value_name='education').drop(
'variable', axis=1).dropna().sort_values(by=['company_id', 'names'])
frame.columns = ['set_name', 'company_id', 'names', 'education']
print(frame)
Result:
set_name company_id names education
2 abc 123c John Smith MS
6 abc 123c John Smith BS
0 abc 123c Oscar MS
4 abc 123c Oscar BS
3 abc 123c Smith, John MS
7 abc 123c Smith, John BS
1 DEF 124b Matt B.