【问题标题】:How to convert pandas dataframe to uniquely structured nested json如何将熊猫数据框转换为结构独特的嵌套 json
【发布时间】:2019-12-23 20:31:05
【问题描述】:

我有一个结构如下的DF:

    traffic_group   app_id  key category    factors
0   desktop         app1    CI  html        16.618628
1   desktop         app1    CI  xhr         35.497082
2   desktop         app1    IP  html        18.294468
3   desktop         app1    IP  xhr         30.422464
4   desktop         app2    CI  html        11.028240
5   desktop         app2    CI  json        33.548279
6   mobile          app1    IP  html        12.808367
7   mobile          app1    IP  image       14.410633

我需要将其输出到以下结构的json:

{ "desktop": {
          app1: [ {
              "key": "CI",
              "threshold: 1,
              "window": 60,
              "factors: {
                   "html" : 16.618628
                   "xhr" : 35.497082
                        }
                  }, {
              "key": "IP",
              "threshold: 1,
              "window": 60,
              "factors: {
                   "html" : 18.294468
                   "xhr" : 30.422464
                        } 
                  ],
           app2: [ {
              "key": "CI",
              "threshold: 1,
              "window": 60,
              "factors: {
                   "html" : 11.028240
                   "json" : 33.548279
                        }
                  }
              },
  "mobile": {
          app1: [  {
              "key": "IP",
              "threshold: 1,
              "window": 60,
              "factors: {
                   "html" : 12.808367
                   "xhr" : 14.410633
                        } 
                 ]
             }
 } 

这个结构无疑是错综复杂的。

我已经考虑了以下以前的答案,并试图模仿他们的逻辑无济于事:

Convert Pandas Dataframe to Custom Nested JSON

convert dataframe to nested json

Pandas Dataframe to Nested JSON

感谢任何帮助。请不要只是发布解决方案,还要解释您的逻辑。

【问题讨论】:

    标签: python json pandas dataframe


    【解决方案1】:

    使用以下方法:

    In [208]: d = {}                                                                                                   
    
    In [209]: grouped = df.groupby(['traffic_group', 'app_id', 'key']).agg(pd.Series.to_dict).to_dict(orient='index')  
    
    In [210]: for t, v in grouped.items(): 
         ...:     traff_gr, app_id, key = t 
         ...:     inner_d = {"key": key, "threshold": 1, "window": 60, 'factors': dict(zip(v['category'].values(), v['f
         ...: actors'].values()))} 
         ...:     d.setdefault(traff_gr, {}).setdefault(app_id, []).append(inner_d) 
         ...:                                                                                                          
    
    In [211]: d                                                                                                        
    Out[211]: 
    {'desktop': {'app1': [{'key': 'CI',
        'threshold': 1,
        'window': 60,
        'factors': {'html': 16.618628, 'xhr': 35.497082}},
       {'key': 'IP',
        'threshold': 1,
        'window': 60,
        'factors': {'html': 18.294468, 'xhr': 30.422464}}],
      'app2': [{'key': 'CI',
        'threshold': 1,
        'window': 60,
        'factors': {'html': 11.02824, 'json': 33.548279}}]},
     'mobile': {'app1': [{'key': 'IP',
        'threshold': 1,
        'window': 60,
        'factors': {'html': 12.808367, 'image': 14.410632999999999}}]}}
    

    【讨论】:

    • 您的解决方案似乎有效,但@Georgios 的回答更“pythonic”,而且他/她的流程清晰且有解释。
    【解决方案2】:

    我在输入中没有看到嵌套字典的任何“阈值”和“窗口”键。让我们假设它们具有固定值。根据您的输出,您似乎希望(通常)为每个三元组(traffic_group、app_id、key)创建一个不同的嵌套字典。因此,我们需要使用这三个键进行初始 groupby 操作。我们为每个组创建嵌套字典:

    def create_nested_dicts(df): 
        return {'key': df['key'].unique()[0], 'threshold': 1, 'window': 60, 'factors': dict(zip(df['category'], df['factors']))}
    
    df = df.groupby(['traffic_group', 'app_id', 'key']).apply(create_nested_dicts)
    

    下一步是将每个 (traffic_group, app_id) doublet 的行组合成列表,并将它们作为字典返回:

    df = df.groupby(['traffic_group', 'app_id']).apply(lambda df: df.tolist())
    

    最后一步是将df 转换为您的输出。有多种方法可以做到这一点。一个简单的如下:

    df = df.reset_index().groupby('traffic_group').apply(lambda df: df.values)
    output = dict(zip(df.index, [{app_id: val for _, app_id, val in vals} for vals in df.values]))                                                                                   
    

    【讨论】:

      【解决方案3】:

      嗯,我已经用“老式”的方式解决了它。为将来可能需要它的任何人发布我的解决方案。不过,如果有人能够使用 pandas 做到这一点,我很乐意看到它。

      json_output = {}
      for traffic_group in sorted_df.traffic_group.unique():
          json_output[traffic_group] = {}
          for app_id in sorted_df[sorted_df.traffic_group == traffic_group].app_id.unique():
              json_output[traffic_group][app_id] = []
              for key in sorted_df[(sorted_df.traffic_group == traffic_group) &
                                   (sorted_df.app_id == app_id)].key.unique():
                  inner_dict = {"key" : key, "threshold" : 1, "window" : 60, "factors" : {}}
                  for category in sorted_df[(sorted_df.traffic_group == traffic_group) & 
                                            (sorted_df.app_id == app_id) & 
                                            (sorted_df.key == key)].category.unique():
                      value = sorted_df[(sorted_df.traffic_group == traffic_group) & 
                                        (sorted_df.app_id == app_id) & 
                                        (sorted_df.key == key) & 
                                        (sorted_df.category == category)].factors  
                      inner_dict["factors"][category] = value.iloc[0]
                  json_output[traffic_group][app_id].append(inner_dict)
      

      【讨论】:

        猜你喜欢
        • 2021-10-08
        • 2020-10-18
        • 2022-01-06
        • 2021-03-30
        • 2020-03-07
        • 2023-03-10
        • 2021-01-19
        • 2017-06-19
        相关资源
        最近更新 更多