【问题标题】:Pandas dataframe to nested dictionary熊猫数据框到嵌套字典
【发布时间】:2018-04-14 05:39:47
【问题描述】:

假设我的数据框看起来像这样。

date     app_id country val1 val2 val3 val4
2016-01-01  123 US       50   70   80   90
2016-01-02  123 US       60   80   90   100
2016-01-03  123 US       70   88   99   11

我想将其转储到嵌套字典甚至 JSON 对象中,如下所示:

{
   country:
   {
       app_id: 
       {
           date: [val1, val2, val3, val4]
       }
    }
}

这样,如果我打电话给my_dict['US'[123['2016-01-01']]],我就会进入列表[50,70,80,90]

有没有一种优雅的方式来做到这一点?我知道 Pandas 的 to_dict() 函数,但我似乎无法绕过嵌套字典。

【问题讨论】:

标签: python pandas


【解决方案1】:

首先创建您需要的数据框。然后使用 DSM 的 recur_dictify

dd=df.groupby(['country','app_id','date'],as_index=False)['val1', 'val2', 'val3', 'val4'].apply(lambda x : x.values.tolist()[0]).to_frame()

def recur_dictify(frame):
    if len(frame.columns) == 1:
        if frame.values.size == 1: return frame.values[0][0]
        return frame.values.squeeze()
    grouped = frame.groupby(frame.columns[0])
    d = {k: recur_dictify(g.iloc[:,1:]) for k,g in grouped}
    return d


recur_dictify(dd.reset_index())
Out[711]: 
{'US': {123: {'2016-01-01': [50, 70, 80, 90],
   '2016-01-02': [60, 80, 90, 100],
   '2016-01-03': [70, 88, 99, 11]}}}

【讨论】:

    【解决方案2】:

    更新

    实际上这可能适用于简单的嵌套字典:

    import pandas as pd
    from collections import defaultdict
    
    nested_dict = lambda: defaultdict(nested_dict)
    output = nested_dict()
    
    for lst in df.values:
        output[lst[1]][lst[0]][lst[2]] = lst[3:].tolist()
    

    或者:

    output = defaultdict(dict)
    
    for lst in df.values:
        try:
            output[lst[1]][lst[0]].update({lst[2]:lst[3:].tolist()})
        except KeyError:
            output[lst[1]][lst[0]] = {}
        finally:
            output[lst[1]][lst[0]].update({lst[2]:lst[3:].tolist()})
    

    或者:

    output = defaultdict(dict)
    
    for lst in df.values:
    
        if output.get(lst[1], {}).get(lst[0]) == None:
            output[lst[1]][lst[0]] = {}        
        output[lst[1]][lst[0]].update({lst[2]:lst[3:].tolist()})
    
    output
    

    这是我的旧解决方案,我们使用df.groupby按国家和app_id 对数据框进行分组。从这里我们收集数据(不包括国家和app_id)并使用defaultdict(dict)以嵌套方式将数据添加到输出字典。

    import pandas as pd
    from collections import defaultdict
    
    output = defaultdict(dict)
    
    groups = ["country","app_id"]
    cols = [i for i in df.columns if i not in groups]
    
    for i,subdf in df.groupby(groups):
        data = subdf[cols].set_index('date').to_dict("split") #filter away unwanted cols
        d = dict(zip(data['index'],data['data'])) 
        output[i[0]][i[1]] = d # assign country=level1, app_id=level2
    
    output
    

    返回:

    {'FR': {123: {'2016-01-01': [10, 20, 30, 40]}},
     'US': {123: {'2016-01-01': [50, 70, 80, 90],
       '2016-01-02': [60, 80, 90, 100],
       '2016-01-03': [70, 88, 99, 11]},
      124: {'2016-01-01': [10, 20, 30, 40]}}}
    

    output['US'][123]['2016-01-01'] 返回:

    [50, 70, 80, 90]
    

    如果:

    df = pd.DataFrame.from_dict({'app_id': {0: 123, 1: 123, 2: 123, 3: 123, 4: 124},
     'country': {0: 'US', 1: 'US', 2: 'US', 3: 'FR', 4: 'US'},
     'date': {0: '2016-01-01',
      1: '2016-01-02',
      2: '2016-01-03',
      3: '2016-01-01',
      4: '2016-01-01'},
     'val1': {0: 50, 1: 60, 2: 70, 3: 10, 4: 10},
     'val2': {0: 70, 1: 80, 2: 88, 3: 20, 4: 20},
     'val3': {0: 80, 1: 90, 2: 99, 3: 30, 4: 30},
     'val4': {0: 90, 1: 100, 2: 11, 3: 40, 4: 40}})
    

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2021-02-15
      • 2019-03-26
      • 1970-01-01
      • 2022-11-17
      • 2019-01-11
      相关资源
      最近更新 更多