【问题标题】:Json normalizing with pandas json_normalize for dynamic records and inner arrays使用 pandas json_normalize 对动态记录和内部数组进行 Json 规范化
【发布时间】:2021-03-22 04:29:22
【问题描述】:

我有以下问题:我正在从mongo集合中读取记录,实际上是json记录,例如以下(测试)记录:

d = {"accounts" : [{"Email" : [{"testclass1":"6b296577-d437-4209-9e91-2fd67b5e7f1e@gmail.com","testclass2" : "6b296577-d437-4209-9e91-2fd67b5e7f1e__PI_1_1","testclass3" : "6b296577-d437-4209-9e91-2fd67b5e7f1e__PI_1_1"}],"bank_id" : "test14-bank","views_available" : [{"is_public" : "True","short_name" : "HHH","id" : "1"}],"Data_Type_test_Boolean" : "True","Data_Type_test_Number" : "44444444","pi_values" : ["6b296577-d437-4209-9e91-2fd67b5e7f1e@gmail.com","6b296577-d437-4209-9e91-2fd67b5e7f1e__PI_1_1","6b296577-d437-4209-9e91-2fd67b5e7f1e__PI_1_1"],"id" : "e01e1118-6143-428d-881c-b04a20b54076","label" : "My account label","sensitivity" : "sensitivity_data"}]}

问题 #1:

我希望最终收到一个完全扁平化的 pandas 数据框,其中包含以下列:account.Email.testclass1、..、accounts.views_available.is_public...

我试过了:

>> pd.json_normalize(d,record_path="accounts").columns
>> Index: Index(['Email', 'bank_id', 'views_available', 'Data_Type_test_Boolean',
       'Data_Type_test_Number', 'pi_values', 'id', 'label', 'sensitivity',
       'accounts'],
      dtype='object')

但这还不够,因为它错过了整个 accounts.views_available.is_public 层次结构,这实际上是一个内部数组对象。 我搜索了很多,但没有找到任何方法来处理这种情况。

有没有办法将 单行 传递给 json_normalize 函数我需要的结果所需的所有记录路径(“外部”和“内部”)?

我知道诸如 Normalizing json list as values 此处建议的解决方案,但想知道是否有更清洁(如更少行)选项。

问题 #2:

如上所述,我正在将 mongo 集合中的多条记录读取到数据框中,其中从一条记录到另一条记录的 json 结构可能会发生变化。也就是说,示例中的 dict d 可能在不同的记录中具有不同的结构(表示为 json 的部分原因......)。 理想情况下,我希望能够在整个 mongo-records 数据帧上使用 json_normalize 函数(并为其提供字典列表),但由于 json 结构可能因记录而异,我不确定它是否可行。

任何建议将不胜感激

【问题讨论】:

    标签: python json pandas


    【解决方案1】:

    不幸的是,我认为 json_normalize() 的单行代码不会削减它。目前尚不清楚从一个记录到下一个记录会发生什么变化。此特定记录具有以下结构:

    list(d['accounts'][0].keys())
    ['Email',
     'bank_id',
     'views_available',
     'Data_Type_test_Boolean',
     'Data_Type_test_Number',
     'pi_values',
     'id',
     'label',
     'sensitivity']
    

    其中 Email 和 views_available 都是字典,但 pi_values 是一个列表,如果将其展平,则需要更多的工作才能进入一行。您可以尝试以下操作,看看是否有任何问题。

    dfe = pd.json_normalize(d['accounts'], record_path=['Email'],
        meta=['bank_id', 'Data_Type_test_Boolean', 'Data_Type_test_Number', 'id', 'label', 'sensitivity'],
        record_prefix='accounts.Email.')
    print(dfe)
    
    dfv = pd.json_normalize(d['accounts'], record_path=['views_available'],
        record_prefix='accounts.views_available.')
    print(dfv)
    
    df = pd.json_normalize(d['accounts'], record_path=['pi_values'],
        record_prefix='accounts.pi_values.').T.reset_index(drop=True)
    new_cols = ['accounts.pi_values.'+str(v) for v in dfp.columns.tolist()]
    df.columns = new_cols
    print(df)
    
    df_final = pd.concat([dfe, dfv, df], axis=1)
    print(df_final)
    

    最终展平数据框中的列名

    Index(['accounts.Email.testclass1', 'accounts.Email.testclass2',
           'accounts.Email.testclass3', 'bank_id', 'Data_Type_test_Boolean',
           'Data_Type_test_Number', 'id', 'label', 'sensitivity',
           'accounts.views_available.is_public',
           'accounts.views_available.short_name', 'accounts.views_available.id',
           'accounts.pi_values.0', 'accounts.pi_values.1', 'accounts.pi_values.2'],
          dtype='object')
    

    【讨论】:

      猜你喜欢
      • 2019-12-17
      • 2013-06-30
      • 2021-07-23
      • 1970-01-01
      • 1970-01-01
      • 2021-12-15
      • 2018-12-07
      • 2018-12-27
      • 1970-01-01
      相关资源
      最近更新 更多