Pandas - 在数据框中的列中展开嵌套的 json 数组

新手上路,请多包涵

我有一个 json 数据(来自 mongodb),其中包含数千条记录(因此是一个 json 对象的数组/列表),每个对象的结构如下所示:

 {
   "id":1,
   "first_name":"Mead",
   "last_name":"Lantaph",
   "email":"mlantaph0@opensource.org",
   "gender":"Male",
   "ip_address":"231.126.209.31",
   "nested_array_to_expand":[
      {
         "property":"Quaxo",
         "json_obj":{
            "prop1":"Chevrolet",
            "prop2":"Mercy Streets"
         }
      },
      {
         "property":"Blogpad",
         "json_obj":{
            "prop1":"Hyundai",
            "prop2":"Flashback"
         }
      },
      {
         "property":"Yabox",
         "json_obj":{
            "prop1":"Nissan",
            "prop2":"Welcome Mr. Marshall (Bienvenido Mister Marshall)"
         }
      }
   ]
}

当加载到数据框中时,“nested_array_to_expand”是一个包含 json 的字符串(我在加载期间确实使用了“json_normalize”)。预期的结果是获得一个包含 3 行的数据框(给定上面的示例)和嵌套对象的新列,如下所示:

 index   email first_name gender  id      ip_address last_name  \
0  mlantaph0@opensource.org       Mead   Male   1  231.126.209.31   Lantaph
1  mlantaph0@opensource.org       Mead   Male   1  231.126.209.31   Lantaph
2  mlantaph0@opensource.org       Mead   Male   1  231.126.209.31   Lantaph

  test.name                                      test.obj.ahah test.obj.buzz
0     Quaxo                                      Mercy Streets     Chevrolet
1   Blogpad                                          Flashback       Hyundai
2     Yabox  Welcome Mr. Marshall (Bienvenido Mister Marshall)        Nissan

我能够使用以下函数获得该结果但它非常慢(1k 记录大约 2s)所以我想改进现有代码或找到一种完全不同的方法来获得这个结果。

 def expand_field(field, df, parent_id='id'):
    all_sub = pd.DataFrame()
    # we need an id per row to be able to merge back dataframes
    # if no id, then we will create one based on index of rows
    if parent_id not in df:
        df[parent_id] = df.index

    # go through all rows and create a new dataframe with values
    for i, row in df.iterrows():
        try:
            sub = json_normalize(df[field].values[i])
            sub = sub.add_prefix(field + '.')
            sub['parent_id'] = row[parent_id]
            all_sub = all_sub.append(sub)
        except:
            print('crash')
            pass
    df = pd.merge(df, all_sub, left_on=parent_id, right_on='parent_id', how='left')
    #remove old columns
    del df["parent_id"]
    del df[field]
    #return expanded dataframe
    return df

非常感谢您的帮助。

===== 编辑以回答评论====

从 mongodb 加载的数据是一个对象数组。我用下面的代码加载它:

 data = json.loads(my_json_string)
df = json_normalize(data)

输出给我一个数据框,其中 df[“nested_array_to_expand”] 作为 dtype 对象(字符串)

 0    [{'property': 'Quaxo', 'json_obj': {'prop1': '...
Name: nested_array_to_expand, dtype: object

原文由 Eric D. 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 782
1 个回答

我提出了一个有趣的答案,我认为使用 pandas.json_normalize

我用它来扩展嵌套的 json 也许有更好的方法,但你绝对应该考虑使用这个特性。然后您只需根据需要重命名列。

 import io
from pandas import json_normalize

# Loading the json string into a structure
json_dict = json.load(io.StringIO(json_str))

df = pd.concat([pd.DataFrame(json_dict),
                json_normalize(json_dict['nested_array_to_expand'])],
                axis=1).drop('nested_array_to_expand', 1)

在此处输入图像描述

原文由 Romain 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题