【问题标题】:Pandas dataframe from nested dictionary来自嵌套字典的 Pandas 数据框
【发布时间】:2016-02-10 06:08:16
【问题描述】:

我的字典是这样的:

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

我想得到一个如下所示的数据框:

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()])

【问题讨论】:

    标签: python dictionary pandas dataframe


    【解决方案1】:

    您可以使用列表推导将您的 dict 重新排序为一个元组列表,其中每个元组是一行,然后您可以对数据帧进行排序

    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
    

    【讨论】:

    • 您可以编辑它以使用任意深度的字典吗?就我而言,我的深度为 4,但理想情况下,我希望看到一个通用的解决方案。谢谢
    • @BaronYugovich 你能添加一个更深入的例子吗
    • 我接受这个答案是因为我能够概括它,概括添加到我原来的问题中。
    • @BaronYugovich 如果你想完全通用,你需要使用递归。
    【解决方案2】:

    首先使用from_dict创建df,然后调用stackreset_index得到你想要的形状,然后你需要重命名cols,排序和重置索引:

    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
    

    【讨论】:

    • 这适用于嵌套更深的字典吗?
    • 视情况而定,但我会说不,因为 ctor 对结构做出假设,因此您可能需要先展开字典
    • 您能否编辑您的回复以解决此问题?我的字典有深度 4,即 (key1, key2, key3, key4, val),你懂的。
    • 很抱歉,但是将您的要求调整为您的 real 数据集和问题在 SO 上是不受欢迎的。您应该将其发布为您真正的问题,或者您应该发布一个新问题,因为这会浪费人们回答不代表您真正问题的问题的时间,因为您实际上是在增加您的要求
    • 抱歉,我在最初的问题中没有强调字典可以更深入。问题是,很难打出一个合适的例子,所以我简化了它。我将在这里编辑我的问题。
    【解决方案3】:

    对于任何深度,您都可以使用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 上还有一些其他示例

    【讨论】:

      猜你喜欢
      • 2015-05-30
      • 2019-02-23
      • 2022-07-14
      • 2016-11-13
      • 1970-01-01
      • 2018-05-04
      • 2019-11-16
      • 2017-06-16
      • 2021-02-15
      相关资源
      最近更新 更多