【问题标题】:How to change json data into dataframe?如何将json数据更改为数据框?
【发布时间】:2020-12-24 14:13:37
【问题描述】:

我需要帮助将 json 数据转换为数据框。你能帮我怎么做吗?

例子:

JSON 数据

{
    "user_id": "vmani4",
    "password": "*****",
    "api_name": "KOL",
    "body": {
      "api_name": "KOL",
      "columns": [
        "kol_id",
        "jnj_id",
        "kol_full_nm",
        "thrc_cd"
      ],
      "filter": {
        "kol_id": "101152",
        "jnj_id": "7124166",
        "thrc_nm": "VIR"
        
      }
    }
}

理想的输出:

user_id     password       api_name     columns       filter     filter_value
vmani        ******         KOL          kol_id       kol_id       101152
                                         jnj_id       jnj_id       7124166
                                         kol_full_nm  thrc_nm      VIR
                                         thrc_cd

【问题讨论】:

    标签: python json python-3.x pandas json-normalize


    【解决方案1】:
    • data 将是 JSON
    • 使用pandas.json_normalize 将JSON 加载到DataFrame,并删除不需要的列。
    • 使用pandas.DataFrame.explode,将'body.columns' 列表展开为单独的行。
    • data['body']['filter'] 创建一个单独的DataFrame
    • 使用pandas.DataFrame.join 组合两个DataFrames
    • 无法将所有'filter' 映射到所有'body.columns'
      • 'thrc_nm' 不映射到 'body.columns' 中的任何内容。
      • 'filter''filter_value' 作为单独的列添加,按它们在 JSON 中的顺序排序,并且与 'body.columns' 无关。
    import pandas as pd
    
    # load the json data
    df = pd.json_normalize(data).drop(columns=['body.filter.kol_id', 'body.filter.jnj_id', 'body.filter.thrc_nm'])
    
    # explode the column
    df = df.explode('body.columns').reset_index(drop=True)
    
    # load and clean data[body][filter]
    df_filter = pd.DataFrame.from_dict(data['body']['filter'], orient='index').reset_index().rename(columns={'index': 'filter', 0: 'filter_value'})
    
    # join the dataframes
    dfj = df.join(df_filter)
    
    # display(dfj)
      user_id password api_name body.api_name body.columns   filter filter_value
    0  vmani4    *****      KOL           KOL       kol_id   kol_id       101152
    1  vmani4    *****      KOL           KOL       jnj_id   jnj_id      7124166
    2  vmani4    *****      KOL           KOL  kol_full_nm  thrc_nm          VIR
    3  vmani4    *****      KOL           KOL      thrc_cd      NaN          NaN
    

    选项

    • 我认为将每个过滤器作为一列更容易,其下方的值
    # load data into a dataframe
    df = pd.json_normalize(data)
    
    # explode the column
    df = df.explode('body.columns').reset_index(drop=True)
    
    # display(df)
      user_id password api_name body.api_name body.columns body.filter.kol_id body.filter.jnj_id body.filter.thrc_nm
    0  vmani4    *****      KOL           KOL       kol_id             101152            7124166                 VIR
    1  vmani4    *****      KOL           KOL       jnj_id             101152            7124166                 VIR
    2  vmani4    *****      KOL           KOL  kol_full_nm             101152            7124166                 VIR
    3  vmani4    *****      KOL           KOL      thrc_cd             101152            7124166                 VIR
    

    【讨论】:

      【解决方案2】:

      我对 DataFrame 不熟悉,但我已尽力以适当的方式提出您所需输出的解决方案。

      代码

      import pandas as pd
      import json
      import numpy as np
      
      json_data = """ {
          "user_id": "vmani4",
          "password": "*****",
          "api_name": "KOL",
          "body": {
            "api_name": "KOL",
            "columns": [
              "kol_id",
              "jnj_id",
              "kol_full_nm",
              "thrc_cd"
            ],
            "filter": {
              "kol_id": "101152",
              "jnj_id": "7124166",
              "thrc_nm": "VIR"
              
            }
          }
      }"""
      
      python_data = json.loads(json_data)
      
      filter = {}
      list_for_filter = []
      filter_value = {}
      list_for_filter_value = []
      first_level = {}
      for_colums = {}
      
      for x, y in python_data.items():
          if type(y) is dict:
              for j, k in y.items():
                  if j == 'columns':
                      for_colums[j] = k
                  if type(k) is dict:
                      for m, n in k.items():
                          list_for_filter.append(m)
                          list_for_filter_value.append(n)
              break
          first_level[x] = [y]
      
      filter['filter'] = list_for_filter
      filter_value['filter_value'] = list_for_filter_value
      
      res = {**first_level, **for_colums, **filter, **filter_value}
      
      df = pd.concat([pd.Series(v, name=k) for k, v in res.items()], axis=1)
      print(df)
      
      

      输出

        user_id password api_name      columns   filter filter_value
      0  vmani4    *****      KOL       kol_id   kol_id       101152
      1     NaN      NaN      NaN       jnj_id   jnj_id      7124166
      2     NaN      NaN      NaN  kol_full_nm  thrc_nm          VIR
      3     NaN      NaN      NaN      thrc_cd      NaN          NaN
      

      让我简要介绍一下我的代码首先创建了很多 listsdicts 我这样做的原因是我在您想要的输出中看到了一些实际上不在您的代码中的列,例如 @ 987654325@.

      我还循环遍历 dict 项,以制作另一个满足所需输出的 ​​dict。

      毕竟因为 DataFrame 中列表的长度不相等,这就是我使用 concatseries 的原因

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-10
        • 2016-04-16
        • 1970-01-01
        • 2020-06-13
        • 2020-05-18
        • 2016-08-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多