【问题标题】:Pandas dataframe to hierarchical dictionary熊猫数据框到分层字典
【发布时间】:2018-06-24 07:43:20
【问题描述】:

我有一个 4 列的 DataFrame

Subject_id    Subject         Time  Score    
Subject_1        Math          Day      1     
Subject_1        Math        Night      2                           
Subject_1       Music          Day      3
Subject_1       Music        Night      4
Subject_2        Math          Day      5       
Subject_2        Math        Night      6                              
Subject_2       Music          Day      7
Subject_2       Music        Night      8

我想对这些列进行分层分组并将它们转换为字典,如下所示:

result = {
    'Subject_1': {
        'Math': {
            'Day': 1,
            'Night': 2 
        },
        'Music': {
            'Day': 3,
            'Night': 4
        }
    }
    'Subject_2': {
        'Math': {
            'Day': 5,
            'Night': 6
        },
        'Music': {
            'Day': 7,
            'Night': 8
        }
    }
}

我设法使用少一列的pivot 并获得了想要的结果

df.pivot('Subject_id', 'Subject', 'Score').to_dict('index')

但是如果我再尝试一列(更深一层的字典)

df.pivot('Subject_id', 'Subject', 'Time', 'Score').to_dict('index')

我得到错误:

TypeError: pivot() takes at most 4 arguments (5 given)

我同样尝试过将 groupby 与 3 列的 lambda 函数一起使用:

df.groupby('Subject_id')
   .apply(lambda x: dict(zip(x['Subject'],x['Score'])))
   .to_dict()

但我无法通过 4 列获得所需的结果。

有没有办法可以给出任意数量的列并将它们转换为分层字典?

就像按特定层次结构顺序按多个字段分组一样。

【问题讨论】:

    标签: python pandas dictionary dataframe


    【解决方案1】:

    这是一种方法

    In [86]: {k: g.pivot('Subject', 'Time', 'Score').to_dict('index') 
              for k, g in df.groupby('Subject_id')}
    Out[86]:
    {'Subject_1': {'Math': {'Day': 1, 'Night': 2},
      'Music': {'Day': 3, 'Night': 4}},
     'Subject_2': {'Math': {'Day': 5, 'Night': 6},
      'Music': {'Day': 7, 'Night': 8}}}
    

    【讨论】:

      【解决方案2】:

      defaultdict 接近。

      def rec_dd():
          return defaultdict(rec_dd)
      
      dd = rec_dd()  # defaultdict for arbitrary depth
      tuple_d = df.set_index(['Subject_id', 'Subject', 'Time']).to_dict()["Score"]
      
      for k, v in tuple_d.items():
          dd[k[0]][k[1]][k[2]] = v
      
      defaultdict(<function __main__.rec_dd>,
              {'Subject_1': defaultdict(<function __main__.rec_dd>,
                           {'Math': defaultdict(<function __main__.rec_dd>,
                                        {'Day': 1, 'Night': 2}),
                            'Music': defaultdict(<function __main__.rec_dd>,
                                        {'Day': 3, 'Night': 4})}),
               'Subject_2': defaultdict(<function __main__.rec_dd>,
                           {'Math': defaultdict(<function __main__.rec_dd>,
                                        {'Day': 5, 'Night': 6}),
                            'Music': defaultdict(<function __main__.rec_dd>,
                                        {'Day': 7, 'Night': 8})})})
      

      方法rec_dd取自@AndrewClark在defaultdict of defaultdict, nested中的回答

      如果你不想要defaultdict,你可以试试下面的

      import json
      d = json.loads(json.dumps(dd))
      
      {'Subject_1': {'Math': {'Day': 1, 'Night': 2},
        'Music': {'Day': 3, 'Night': 4}},
       'Subject_2': {'Math': {'Day': 5, 'Night': 6},
        'Music': {'Day': 7, 'Night': 8}}}
      

      defaultdict 变成dict 的方法取自@Meow 在Python: convert defaultdict to dict 中的回答

      【讨论】:

        猜你喜欢
        • 2016-10-17
        • 2017-08-02
        • 2017-02-27
        • 2012-09-17
        • 2020-07-23
        • 1970-01-01
        • 2021-07-17
        • 2020-07-22
        • 2021-10-26
        相关资源
        最近更新 更多