【问题标题】:Flatten nested JSON (has multiple list) into multiple pandas dataframe columns将嵌套的 JSON(具有多个列表)展平为多个 pandas 数据框列
【发布时间】:2022-01-04 07:36:21
【问题描述】:

我有一个带有嵌套 json 数据字符串的 pandas 列。我想将数据展平为多个熊猫列。 我有这样的数据:

{
 'A': '123',
 'B': '2019-08-26', 
 'C': [
       {
        'a': 'stop', 
        'b': 'A+'
       },
       {
        'a': 'go', 
        'b': 'C+'
       }
      ], 
'D': [],
'E': [
      {
       'a': 'Don', 
      'b': 1
      },
      {
       'b': 12
      }
     ], 
}

对于 pandas 列中的每个单元格,我想解析这个字符串并创建多个列。预期输出如下所示:

| A | B | C.a | C.b | D.a | D.b | E.a | E.b |
|---- |------|-----|-----|-----|-----|-----|-----|
| 123  | 2019-08-26  | stop | A+ | Nan | Nan | Don | 1 |
| 123  | 2019-08-26  | go | C+ | Nan | Nan | Don | 1 |
| 123  | 2019-08-26  | stop | A+ | Nan | Nan | NaN | 12 |
| 123  | 2019-08-26  | go | C+ | Nan | Nan | Nan | 12 |

我尝试使用 json_normalize,但它返回错误.... 请帮帮我:(

【问题讨论】:

    标签: python json pandas dataframe


    【解决方案1】:

    pd.json_normalizedf.explodepd.concat 一起使用:

    In [308]: x = pd.json_normalize(j).explode('C').explode('E')  
    In [310]: r = pd.concat([x.drop(['C', 'E'], 1).reset_index(drop=True), pd.json_normalize(x.C), pd.json_normalize(x.E)], 1)
    
    In [316]: C_cols = [f'C.{i}' for i in pd.json_normalize(x.C).columns]    
    In [317]: E_cols = [f'E.{i}' for i in pd.json_normalize(x.E).columns]
    
    In [323]: r.columns = [*x.drop(['C', 'E'], 1).columns , *C_cols, *E_cols]
    
    In [324]: r
    Out[324]: 
         A           B   D   C.a C.b  E.a  E.b
    0  123  2019-08-26  []  stop  A+  Don    1
    1  123  2019-08-26  []  stop  A+  NaN   12
    2  123  2019-08-26  []    go  C+  Don    1
    3  123  2019-08-26  []    go  C+  NaN   12
    

    【讨论】:

      【解决方案2】:

      类似于@Mayank Porwal 的回答,首先使用pd.json_normalize + df.explode。然后使用str.get 方法从['C','D','E'] 列中的字典中收集值:

      df = pd.json_normalize(json_data).explode('C').explode('E')
      for col in ['C','D','E']:
          for i in ['a','b']:
              df[col+'.'+i] = df[col].str.get(i)
      df['E.a'].replace({None:np.nan}, inplace=True)
      df = df.drop(['C','E','D'], axis=1).sort_values(by='E.b')
      

      输出:

           A           B   C.a C.b  D.a  D.b  E.a  E.b
      0  123  2019-08-26  stop  A+  NaN  NaN  Don    1
      0  123  2019-08-26    go  C+  NaN  NaN  Don    1
      0  123  2019-08-26  stop  A+  NaN  NaN  NaN   12
      0  123  2019-08-26    go  C+  NaN  NaN  NaN   12
      

      【讨论】:

        猜你喜欢
        • 2020-09-27
        • 2022-11-23
        • 1970-01-01
        • 2021-01-18
        • 1970-01-01
        • 2022-01-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多