Python namedtuples到dataframe的嵌套字典

Python namedtuples到dataframe的嵌套字典,python,pandas,dictionary,dataframe,namedtuple,Python,Pandas,Dictionary,Dataframe,Namedtuple,我已按如下定义命名了耦合: In[37]: from collections import namedtuple Point = namedtuple('Point', 'x y') df = frame_from_dict(d, names=['Subcase', 'Step', 'ID']).T df.columns = ['x', 'y'] df Out[115]: x y Subcase Step ID

我已按如下定义命名了耦合:

In[37]: from collections import namedtuple
        Point = namedtuple('Point', 'x y')
df = frame_from_dict(d, names=['Subcase', 'Step', 'ID']).T
df.columns = ['x', 'y']
df
Out[115]: 
                       x        y
Subcase Step ID                  
1       NaN  1       1.0      5.0
             2       4.0      8.0
2       NaN  1   45324.0  24338.0
             2      45.0     38.0
嵌套字典具有以下格式:

In[38]: d
Out[38]: 
{1: {None: {1: Point(x=1.0, y=5.0), 2: Point(x=4.0, y=8.0)}},
2: {None: {1: Point(x=45324.0, y=24338.0), 2: Point(x=45.0, y=38.0)}}}
我试图从字典d创建一个pandas数据帧,而不必执行for循环

通过以下操作,我成功地从字典的子集创建了dataframe:

In[40]: df=pd.DataFrame(d[1][None].values())

In[41]: df

Out[41]: 
   x  y
0  1  5
1  4  8
但是我希望能够从整个字典中创建数据帧

我希望数据帧输出以下内容(我使用多索引表示法):

DataFrame的from_dict方法最多只支持两级嵌套,因此我无法使用它。我也在考虑修改d字典的结构以实现我的目标。此外,也许它不一定是一本字典


谢谢。

关于SO(,或)的类似问题,已经有好几个答案了。这些解决方案也可以适应这个问题。然而,没有一个是真正通用的,可以在任意的dict上运行的。所以我决定写一些更通用的东西

这是一个可以在任何dict上运行的函数。dict必须在其任何元素上具有相同数量的级别(深度),否则它很可能会升高

def frame_from_dict(dic, depth=None, **kwargs):
    def get_dict_depth(dic):
        if not isinstance(dic, dict):
            return 0
        for v in dic.values():
            return get_dict_depth(v) + 1

    if depth is None:
        depth = get_dict_depth(dic)

    if depth == 0:
        return pd.Series(dic)
    elif depth > 0:
        keys = []
        vals = []
        for k, v in dic.items():
            keys.append(k)
            vals.append(frame_from_dict(v, depth - 1))
        try:
            keys = sorted(keys)
        except TypeError:
            # unorderable types
            pass
        return pd.concat(vals, axis=1, keys=keys, **kwargs)

    raise ValueError("depth should be a nonnegative integer or None")
为了一般性,我牺牲了这个问题中的一个命名案例。但如果需要,可以对其进行调整

在这种特殊情况下,可按如下方式应用:

In[37]: from collections import namedtuple
        Point = namedtuple('Point', 'x y')
df = frame_from_dict(d, names=['Subcase', 'Step', 'ID']).T
df.columns = ['x', 'y']
df
Out[115]: 
                       x        y
Subcase Step ID                  
1       NaN  1       1.0      5.0
             2       4.0      8.0
2       NaN  1   45324.0  24338.0
             2      45.0     38.0

我决定将这些键展平为一个元组(使用pandas 0.18.1进行测试):

最后,

In [7]: import pandas as pd

In [8]: df=pd.DataFrame(d.values(),  index=pd.MultiIndex.from_tuples(d.keys(), names=['Subcase','Step','ID']))


In [9]:df
Out[9]: 
                       x        y
Subcase Step ID                  
1       NaN  1       1.0      5.0
             2       4.0      8.0
2       NaN  1   45324.0  24338.0
             2      45.0     38.0

你说它不一定是一个dict-dict中的数据来源是什么?或者您是指在将dict转换为数据帧之前将其转换为中间结构吗?数据源来自二进制文件。为了便于访问和快速查询,它被转换为dict。我想说的是,我可以修改将二进制文件更改为dict的代码,并使用对熊猫更友好的代码。转换dict似乎效率很低。谢谢你,它工作起来很有魅力。我知道这个解决方案,但我特别尝试避免使用for循环,因为我可以控制字典的定义。我决定把这些键平铺成一个元组。见解决方案below@snowleopard我懂了。有没有一种将嵌套字典的键展平为元组的通用方法?我认为这是问题的症结所在。是的,你是对的,但我是从一个二进制文件创建字典的,所以我可以控制字典的定义。啊,好的。直接创建元组是一种更好的方法。