【问题标题】:Normalizing nested json data with pandas使用 pandas 规范化嵌套的 json 数据
【发布时间】:2019-12-22 23:59:21
【问题描述】:

我正在尝试使用嵌套的 json,但没有达到我想要的结果。

我有一个这样的 JSON 数据:

{'from_cache': True,
 'results': [{'data': [{'date': '2019/06/01', 'value': 0},
                   {'date': '2019/06/02', 'value': 0},
                   {'date': '2019/08/09', 'value': 7087},
                   {'date': '2019/08/10', 'value': 0},
                   {'date': '2019/08/11', 'value': 15},
                   {'date': '2019/08/12', 'value': 14177},
                   {'date': '2019/08/13', 'value': 0}],
          'name': 'Clicks'},
     {'data': [{'date': '2019/06/01', 'value': 0.0},
                   {'date': '2019/06/02', 'value': 0.0},
                   {'date': '2019/06/03', 'value':1.0590561064390611},
                   {'date': '2019/08/11', 'value':1.8610421836228286},
                   {'date': '2019/08/12', 'value': 6.191613785151832},
                   {'date': '2019/08/13', 'value': 0.0}],
          'name': 'Rate'}]}

预期的结果是这样的数据框:

date         Clicks   Rate
2019/06/01   0        0.0
2019/06/02   0        0.0
2019/08/09   7087     1.0590561064390611

如您所见,我希望每个“名称”都作为具有相应“值”的数据框列。

我正在使用 pd.io.json_normalize,但没有成功获得此结果。我达到的最佳结果是包含以下列的数据框:日期、值、名称。

有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: python json pandas dataframe nested


    【解决方案1】:

    IIUC,使用pd.concataxis=1

    df = pd.concat([pd.DataFrame(k['data']).rename(columns={'value': k['name']})\
                                           .set_index('date') 
                    for k in d['results']], 
                    sort=False, 
                    axis=1)
    

                 Clicks      Rate
    2019/06/01      0.0  0.000000
    2019/06/02      0.0  0.000000
    2019/08/09   7087.0       NaN
    2019/08/10      0.0       NaN
    2019/08/11     15.0  1.861042
    2019/08/12  14177.0  6.191614
    2019/08/13      0.0  0.000000
    2019/06/03      NaN  1.059056
    

    pivot_table 的另一种方式

    df = pd.concat([pd.DataFrame(x['data']).assign(column=x['name']) for x in d['results']])\
           .pivot_table(columns='column', index='date', values='value')
    

    【讨论】:

      【解决方案2】:

      没有循环:

      from pandas.io.json import json_normalize
      import matplotlib.pyplot as plt
      
      df = json_normalize(data['results'], record_path=['data'], meta=['name'])    
      df.date = pd.to_datetime(df.date)
      
      df_clicks = df[df.name == 'Clicks'].drop('name', axis=1).rename(columns={'value': 'Clicks'})
      df_rate = df[df.name == 'Rate'].drop('name', axis=1).rename(columns={'value': 'Rate'})
      
      df_final = df_clicks.merge(df_rate, how='outer', sort=True)
      df_final.set_index('date', drop=True, inplace=True)
      

      • 意外数据:
        • 2019-06-03:无点击率
        • 2019-08-09:点击次数,但没有费率

      绘制它:

      df_final.plot(kind='bar', logy=True)
      plt.show()
      

      建议的新json格式:

      data = {'from_cache': True,
              'results': [{'date': '2019/06/01', 'Clicks': 0, 'Rate': 0},
                          {'date': '2019/06/02', 'Clicks': 0, 'Rate': 0},
                          {'date': '2019/06/03', 'Clicks': 0, 'Rate': 1.0590561064390611},
                          {'date': '2019/08/09', 'Clicks': 7087, 'Rate': 0},
                          {'date': '2019/08/10', 'Clicks': 0, 'Rate': 0},
                          {'date': '2019/08/11', 'Clicks': 15, 'Rate': 1.8610421836228286},
                          {'date': '2019/08/12', 'Clicks': 14177, 'Rate': 6.191613785151832},
                          {'date': '2019/08/13', 'Clicks': 0, 'Rate': 0}]}
      

      【讨论】:

      • 这真是一个很棒的解决方案!非常感谢您的帮助!
      猜你喜欢
      • 2020-06-21
      • 2021-04-18
      • 2021-12-12
      • 2018-04-09
      • 2018-05-23
      • 1970-01-01
      • 2021-07-23
      • 2018-12-07
      • 1970-01-01
      相关资源
      最近更新 更多