从嵌套字典创建Pandas数据框架

8

我的字典长这样:

{'x': {'b': 10, 'c': 20}, 'y': {'b': '33', 'c': 44}}

我要获得一个像这样的数据框:
```html

我要获得一个像这样的数据框:

```
index   col1    col2    val
0        x       b      10
1        x       c      20
2        y       b      33
3        y       c      44

我尝试使用pandas.from_dict()函数,但它没有给我期望的结果。那么,最优雅、实用的方法是什么呢?

编辑:实际上,我的字典深度为4,所以我想看到一个解决这种情况的方法,或者理想情况下,一个适用于任意深度的通用设置。

这里有一个更深层次的字典示例:{'x':{'a':{'m':1, 'n':2}, 'b':{'m':10, 'n':20}}, 'y':{'a':{'m':100, 'n':200}, 'b':{'m':111, 'n':222}} } 相应的数据框应该有8行。

答案:

df = pd.DataFrame([(k1, k2, k3, k4, k5, v) for k1, k2345v in dict.items()
                           for k2, k345v in k2345v.items()
                           for k3, k45v in k345v.items()
                           for k4, k5v in k45v.items()
                           for k5, v in k5v.items()])
3个回答

6

对于任何深度的数据,你可以使用pd.json_normalizemelt。以下是一个稍微修改过的2/3/4层嵌套字典的示例:

data = {'one': 1, 'two': {'a': 2}, 'four': {'a': {'b': {'c': 2}}},
        'x': {'a': {'m': 1, 'n': 2}, 'b': {'m': 10, 'n': 20}},
        'y': {'a': {'m': 100, 'n': 200}, 'b': {'m': 111, 'n': 222}}}
df_melt = pd.json_normalize(data, sep='>>').melt()
df_final = df_melt['variable'].str.split('>>', expand=True)
df_final.columns = [f'col{name}' for name in df_final.columns]
df_final[['value']] = df_melt['value']

    col0  col1  col2  col3  value
0    one  None  None  None      1
1    two     a  None  None      2
2   four     a     b     c      2
3      x     a     m  None      1
4      x     a     n  None      2
5      x     b     m  None     10
6      x     b     n  None     20
7      y     a     m  None    100
8      y     a     n  None    200
9      y     b     m  None    111
10     y     b     n  None    222

json_normalize非常有用,此外还有一些在Medium上的其他示例。


5
你可以使用列表推导式将字典重排序为元组列表,其中每个元组是一行,然后可以对数据框进行排序。
import pandas as pd

d = {'x': {'b': 10, 'c': 20}, 'y': {'b': '33', 'c': 44}}

df = pd.DataFrame([(k,k1,v1) for k,v in d.items() for k1,v1 in v.items()], columns = ['Col1','Col2','Val'])
print df.sort(['Col1','Col2','Val'], ascending=[1,1,1])

  Col1 Col2 Val
3    x    b  10
2    x    c  20
1    y    b  33
0    y    c  44

2
您能否将此编辑为适用于任意深度的字典?在我的情况下,我有四级深度,但理想情况下,我希望看到一个通用解决方案。谢谢。 - Baron Yugovich
@BaronYugovich 你能否添加一个更详细的例子? - SirParselot
我接受这个答案,因为我能够将其推广,推广加强了我的原始问题。 - Baron Yugovich
@BaronYugovich 如果你想要完全通用,你需要使用递归。 - SirParselot

3

首先使用from_dict创建数据框,然后调用stackreset_index来获取所需的形状,接着需要重命名列、排序并重置索引:

In [83]:
d={'x': {'b': 10, 'c': 20}, 'y': {'b': '33', 'c': 44}}
df = pd.DataFrame.from_dict(d, orient='index').stack().reset_index()
df.columns = ['col1', 'col2', 'val']
df.sort_values(['col1', 'col2'], inplace=True)
df.reset_index(drop=True, inplace=True)
df

Out[83]:
  col1 col2 val
0    x    b  10
1    x    c  20
2    y    b  33
3    y    c  44

1
这对于更深层嵌套的字典也适用吗? - Baron Yugovich
取决于情况,但我会说不需要,因为构造函数对结构做出了假设,所以您可能需要先展开字典。 - EdChum
1
请你修改一下回答以适应这点?我的字典深度为4,即(key1,key2,key3,key4,val),你明白我的意思。 - Baron Yugovich
抱歉,但在SO上调整您的要求以适应您的“真实”数据集和问题是不被允许的。您应该将其作为您的真正问题发布,或者您应该发布一个新问题,因为回答不代表您的真正问题,而实际上是在增加您的要求,这浪费了人们的时间。 - EdChum
非常抱歉,我在原始问题中没有强调字典可以更深入。事实上,很难打出一个恰当的示例,所以我简化了它。我将在这里编辑我的问题。 - Baron Yugovich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接