将多索引数据框转换为嵌套字典 - Python
Converting multi index data frame to nested dictionaries - Python
在 Python 我有以下多索引数据框:
level 3
col 1
col 1
col 2
col 3
level 1
level 2
level 3
level 4
col 1a
col 1b
col 2
col 3
A
Aa
Aaa
type1
val 1
val 2
val 3
val 4
A
Aa
Aaa
type2
val 5
val 6
val 7
val 8
A
Ab
Aab
type1
val 9
val 10
...
...
A
Ac
Aac
type2
...
...
...
...
B
Ba
Baa
type1
...
...
...
...
B
Ba
Bab
type3
...
...
...
...
C
Ca
Caa
type4
...
...
...
...
数据框说明:
- 前两行是多索引headers
- 前4列是多索引headers
- 1、2、3、4层及空白处为索引区
从这个列表中,我的目标是得到一个字典,例如:
- 第一个选项是 A、B 或 C
- 如果点击 A,下一个选择是 Aa、Ab 或 Ac
- 如果点击Aa,下一个选择只有Aaa(如果只有Aaa可用)
- 如果点击 Aaa,下一个选择是类型 1 或类型 2
- 如果点击type1,下一个选择是col 1 or col 2 or col3
- 如果点击 col1,下一个选择是 col 1a 或 col 1b
- 如果点击 col 1a,我们发现 val 1 作为最终输出
请指导我如何进行此转换。此外,也非常感谢关于如何处理此案例的新观点和建议。
假设您有以下数据框 df
:
col 1 col 2 col 3
col 1a col 1b col 2 col 3
A Aa Aaa type1 val 1 val 2 val 3 val 4
type2 val 5 val 6 val 7 val 8
Ab Aab type1 val 9 val 10 val 11 val 12
Ac Aac type2 val 13 val 14 val 15 val 16
B Ba Baa type1 val 17 val 18 val 19 val 20
Bab type3 val 21 val 22 val 23 val 24
C Ca Caa type4 val 25 val 26 val 27 val 28
第一步:进一步扁平化:
df_sub = (
df.loc[:, [("col 1", "col 1a"), ("col 1", "col 1b")]]
.melt(ignore_index=False)
.set_index(["variable_0", "variable_1"], append=True)
)
结果:
value
variable_0 variable_1
A Aa Aaa type1 col 1 col 1a val 1
type2 col 1 col 1a val 5
Ab Aab type1 col 1 col 1a val 9
Ac Aac type2 col 1 col 1a val 13
B Ba Baa type1 col 1 col 1a val 17
Bab type3 col 1 col 1a val 21
C Ca Caa type4 col 1 col 1a val 25
A Aa Aaa type1 col 1 col 1b val 2
type2 col 1 col 1b val 6
Ab Aab type1 col 1 col 1b val 10
Ac Aac type2 col 1 col 1b val 14
B Ba Baa type1 col 1 col 1b val 18
Bab type3 col 1 col 1b val 22
C Ca Caa type4 col 1 col 1b val 26
步骤 2:嵌套(递归):
def nest(df):
if df.index.nlevels == 1:
return df.to_dict()[df.columns[0]]
return {
key: nest(df_grp.droplevel(0, axis=0))
for key, df_grp in df.groupby(level=0)
}
result = nest(df_sub)
结果:
{'A': {'Aa': {'Aaa': {'type1': {'col 1': {'col 1a': 'val 1',
'col 1b': 'val 2'}},
'type2': {'col 1': {'col 1a': 'val 5',
'col 1b': 'val 6'}}}},
'Ab': {'Aab': {'type1': {'col 1': {'col 1a': 'val 9',
'col 1b': 'val 10'}}}},
'Ac': {'Aac': {'type2': {'col 1': {'col 1a': 'val 13',
'col 1b': 'val 14'}}}}},
'B': {'Ba': {'Baa': {'type1': {'col 1': {'col 1a': 'val 17',
'col 1b': 'val 18'}}},
'Bab': {'type3': {'col 1': {'col 1a': 'val 21',
'col 1b': 'val 22'}}}}},
'C': {'Ca': {'Caa': {'type4': {'col 1': {'col 1a': 'val 25',
'col 1b': 'val 26'}}}}}}
这是你要找的吗?
第 2 步可以用不同的方式完成:
result = {}
for keys, value in df_sub.itertuples():
last = result
for key in keys[:-1]:
last = last.setdefault(key, {})
last[keys[-1]] = value
在 Python 我有以下多索引数据框:
level 3 | col 1 | col 1 | col 2 | col 3 | |||
---|---|---|---|---|---|---|---|
level 1 | level 2 | level 3 | level 4 | col 1a | col 1b | col 2 | col 3 |
A | Aa | Aaa | type1 | val 1 | val 2 | val 3 | val 4 |
A | Aa | Aaa | type2 | val 5 | val 6 | val 7 | val 8 |
A | Ab | Aab | type1 | val 9 | val 10 | ... | ... |
A | Ac | Aac | type2 | ... | ... | ... | ... |
B | Ba | Baa | type1 | ... | ... | ... | ... |
B | Ba | Bab | type3 | ... | ... | ... | ... |
C | Ca | Caa | type4 | ... | ... | ... | ... |
数据框说明:
- 前两行是多索引headers
- 前4列是多索引headers
- 1、2、3、4层及空白处为索引区
从这个列表中,我的目标是得到一个字典,例如:
- 第一个选项是 A、B 或 C
- 如果点击 A,下一个选择是 Aa、Ab 或 Ac
- 如果点击Aa,下一个选择只有Aaa(如果只有Aaa可用)
- 如果点击 Aaa,下一个选择是类型 1 或类型 2
- 如果点击type1,下一个选择是col 1 or col 2 or col3
- 如果点击 col1,下一个选择是 col 1a 或 col 1b
- 如果点击 col 1a,我们发现 val 1 作为最终输出
请指导我如何进行此转换。此外,也非常感谢关于如何处理此案例的新观点和建议。
假设您有以下数据框 df
:
col 1 col 2 col 3
col 1a col 1b col 2 col 3
A Aa Aaa type1 val 1 val 2 val 3 val 4
type2 val 5 val 6 val 7 val 8
Ab Aab type1 val 9 val 10 val 11 val 12
Ac Aac type2 val 13 val 14 val 15 val 16
B Ba Baa type1 val 17 val 18 val 19 val 20
Bab type3 val 21 val 22 val 23 val 24
C Ca Caa type4 val 25 val 26 val 27 val 28
第一步:进一步扁平化:
df_sub = (
df.loc[:, [("col 1", "col 1a"), ("col 1", "col 1b")]]
.melt(ignore_index=False)
.set_index(["variable_0", "variable_1"], append=True)
)
结果:
value
variable_0 variable_1
A Aa Aaa type1 col 1 col 1a val 1
type2 col 1 col 1a val 5
Ab Aab type1 col 1 col 1a val 9
Ac Aac type2 col 1 col 1a val 13
B Ba Baa type1 col 1 col 1a val 17
Bab type3 col 1 col 1a val 21
C Ca Caa type4 col 1 col 1a val 25
A Aa Aaa type1 col 1 col 1b val 2
type2 col 1 col 1b val 6
Ab Aab type1 col 1 col 1b val 10
Ac Aac type2 col 1 col 1b val 14
B Ba Baa type1 col 1 col 1b val 18
Bab type3 col 1 col 1b val 22
C Ca Caa type4 col 1 col 1b val 26
步骤 2:嵌套(递归):
def nest(df):
if df.index.nlevels == 1:
return df.to_dict()[df.columns[0]]
return {
key: nest(df_grp.droplevel(0, axis=0))
for key, df_grp in df.groupby(level=0)
}
result = nest(df_sub)
结果:
{'A': {'Aa': {'Aaa': {'type1': {'col 1': {'col 1a': 'val 1',
'col 1b': 'val 2'}},
'type2': {'col 1': {'col 1a': 'val 5',
'col 1b': 'val 6'}}}},
'Ab': {'Aab': {'type1': {'col 1': {'col 1a': 'val 9',
'col 1b': 'val 10'}}}},
'Ac': {'Aac': {'type2': {'col 1': {'col 1a': 'val 13',
'col 1b': 'val 14'}}}}},
'B': {'Ba': {'Baa': {'type1': {'col 1': {'col 1a': 'val 17',
'col 1b': 'val 18'}}},
'Bab': {'type3': {'col 1': {'col 1a': 'val 21',
'col 1b': 'val 22'}}}}},
'C': {'Ca': {'Caa': {'type4': {'col 1': {'col 1a': 'val 25',
'col 1b': 'val 26'}}}}}}
这是你要找的吗?
第 2 步可以用不同的方式完成:
result = {}
for keys, value in df_sub.itertuples():
last = result
for key in keys[:-1]:
last = last.setdefault(key, {})
last[keys[-1]] = value