【问题标题】:Getting pandas dataframe from list of nested dictionaries从嵌套字典列表中获取熊猫数据框
【发布时间】:2017-06-16 06:15:36
【问题描述】:

我是 Python 新手,所以这可能很简单,但是在寻找了一段时间后,我无法为我的问题找到一个好的答案。我正在尝试从字典列表中创建一个 Pandas 数据框。

我的嵌套字典列表如下:

my_list = [{0: {'a': '23', 'b': '15', 'c': '5', 'd': '-1'}, 
            1: {'a': '5', 'b': '6', 'c': '7', 'd': '9'}, 
            2: {'a': '9', 'b': '15', 'c': '5', 'd': '7'}}, 
           {0: {'a': '5', 'b': '249', 'c': '92', 'd': '-4'}, 
            1: {'a': '51', 'b': '5', 'c': '34', 'd': '1'}, 
            2: {'a': '3', 'b': '8', 'c': '3', 'd': '11'}}]

所以主字典中的每个键都有 3 个值。

使用data = pd.DataFrame(my_list) 将它们放入数据框中会返回一些不可用的东西,因为每个单元格中都有关于 a、b、c 和 d 的信息。

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

 name| a  | b  | c | d 
0    | 23 | 15 | 5 | -1 
1    | 5  | 6  | 7 |  9 
2    | 9  | 15 | 5 |  7 
0    | 5  |249 | 92| -4 
1    |51  | 5  | 34|  1 
2    | 3  | 8  | 3 | 11 

这可能吗?

【问题讨论】:

    标签: python list pandas dictionary dataframe


    【解决方案1】:

    简单:

    pd.concat([pd.DataFrame(l) for l in my_list],axis=1).T
    

    【讨论】:

      【解决方案2】:

      另一种解决方案:

      from itertools import chain
      pd.DataFrame.from_items(list(chain.from_iterable(d.iteritems() for d in my_list))).T
      

      在我的实验中,这比使用 pd.concat 更快(尤其是当“子数据帧”的数量很大时),但代价是更冗长。

      【讨论】:

      • 非常感谢!当我尝试此代码时,我收到错误:NameError: name 'chain' is not defined。你知道为什么吗?否则,我想我理解这段代码的直觉。
      • 抱歉,忘记指定导入。我使用的是itertools.chain,它是标准库的一部分。请参阅编辑。
      • 谢谢!我会尝试 pd.concat 和这个,因为我确实有很多数据要处理。
      • 只是一个快速更新:我没有看到 pd.concat 和这种方法在处理时间方面有任何巨大差异,可能是因为我的数据集不是那么大(总共 20,000 次观察)。再次感谢您!
      • 我猜观察的数量并不像“块”的数量那么重要。从每个块创建一个DataFrame,然后与pd.concat 进行繁琐的索引对齐会有相当大的开销,但如果你只有几个块,这并不重要。无论如何,很高兴你解决了你的问题。
      【解决方案3】:

      您可以调整字典列表以供 DataFrame 构造函数接受:

      In [4]: pd.DataFrame.from_records([{'name': k, **v} for d in my_list for k,v in d.items()])
      Out[4]:
          a    b   c   d  name
      0  23   15   5  -1     0
      1   5    6   7   9     1
      2   9   15   5   7     2
      3   5  249  92  -4     0
      4  51    5  34   1     1
      5   3    8   3  11     2
      
      In [5]: df = pd.DataFrame.from_records([{'name': k, **v} for d in my_list for k,v in d.items()])
      
      In [6]: df.set_index('name',inplace=True)
      
      In [7]: df
      Out[7]:
             a    b   c   d
      name
      0     23   15   5  -1
      1      5    6   7   9
      2      9   15   5   7
      0      5  249  92  -4
      1     51    5  34   1
      2      3    8   3  11
      

      这需要相对较新版本的 Python,{'name':'something', **rest} 才能工作。它只是以下内容的简写:

      In [13]: reshaped = []
          ...: for d in my_list:
          ...:     for k, v in d.items():
          ...:         new = {'name': k}
          ...:         new.update(v)
          ...:         reshaped.append(new)
          ...:
      
      In [14]: reshaped
      Out[14]:
      [{'a': '23', 'b': '15', 'c': '5', 'd': '-1', 'name': 0},
       {'a': '5', 'b': '6', 'c': '7', 'd': '9', 'name': 1},
       {'a': '9', 'b': '15', 'c': '5', 'd': '7', 'name': 2},
       {'a': '5', 'b': '249', 'c': '92', 'd': '-4', 'name': 0},
       {'a': '51', 'b': '5', 'c': '34', 'd': '1', 'name': 1},
       {'a': '3', 'b': '8', 'c': '3', 'd': '11', 'name': 2}]
      

      【讨论】:

        【解决方案4】:
        from pandas import DataFrame
        
        def flat_dict(data: dict, prefix=''):
            result = dict()
            
            for key in data:
                
                if len(prefix):
                    field = prefix + '_' + key
                else:
                    field = key
                    
                if isinstance(data[key], dict):
                    result.update(
                        flat_dict(data[key], key)
                    )
                else:
                    result[field] = data[key]
            
            return result
        
        refactor_data = map(lambda x: flat_dict(x), data)
        
        df = DataFrame(refactor_data)
        

        【讨论】:

          猜你喜欢
          • 2020-05-23
          • 1970-01-01
          • 2019-01-11
          • 2023-03-23
          • 2018-04-14
          • 2021-02-15
          • 1970-01-01
          相关资源
          最近更新 更多