【问题标题】:How to get mongodb nested documents in Python Pandas dataframe table format如何以 Python Pandas 数据框表格式获取 mongodb 嵌套文档
【发布时间】:2021-12-11 19:14:56
【问题描述】:
name age address
1 "Steve" 27 {"number": 4, "street": "Main Road", "city": "Oxford"}
2 "Adam" 32 {"number": 78, "street": "High St", "city": "Cambridge"}

然而,子文档将在子文档单元格中显示为 JSON

from pandas import DataFrame

df = DataFrame(list(db.collection_name.find({}))
print(df)

如何使用 python 获得如下第二张表?

这之后的方法是什么?

name age address.number address.street address.city
1 Steve 27 4 "Main Road" "Oxford"
2 Adam 32 78 "High St" "Cambridge"

【问题讨论】:

    标签: python pandas mongodb pymongo


    【解决方案1】:

    您可以使用pd.DataFrameaddress 列中的 JSON/dict 扩展为 JSON/dict 内容的数据框。然后,使用.join()加入原始数据框,如下:

    可选步骤:如果您的 JSON/dict 实际上是字符串,请先将它们转换为正确的 JSON/dict。否则,请跳过此步骤。

    import ast
    df['address'] = df['address'].map(ast.literal_eval)
    

    主要代码:

    import pandas as pd
    
    df[['name', 'age']].join(pd.DataFrame(df['address'].tolist(), index=df.index).add_prefix('address.'))
    

    结果:

        name  age  address.number address.street address.city
    1  Steve   27               4      Main Road       Oxford
    2   Adam   32              78        High St    Cambridge
    

    或者,如果您只有几列要从 JSON/dict 添加,您也可以使用字符串访问器 str[] 逐一添加,如下所示

    df['address.number'] = df['address'].str['number']
    df['address.street'] = df['address'].str['street']
    df['address.city'] = df['address'].str['city']
    

    设置

    import pandas as pd
    
    data = {'name': {1: 'Steve', 2: 'Adam'},
            'age': {1: 27, 2: 32},
            'address': {1: {"number": 4, "street": "Main Road", "city": "Oxford"},
                        2: {"number": 78, "street": "High St", "city": "Cambridge"}}}
    df = pd.DataFrame(data)
    

    【讨论】:

    • df['address.number'] = df['address'].str['number'] df['address.street'] = df['address'].str['street '] df['address.city'] = df['address'].str['city'] 这部分很有帮助
    • @usmansharifshaik 是的,如果您只需要有限数量的字段,这是一个不错的选择。如果你有一个很大的 JSON/dict 并且想要其中的所有条目,上面的部分会更方便使用。
    • @usmansharifshaik 除了接受我的回答,您还可以点赞它,如果您觉得它对您有帮助,请点击向上箭头▲(参见How to upvote on Stack Overflow?)。
    【解决方案2】:

    根据用例,设置aggregation 管道和$project 必要的嵌套文档可能更有意义:

    df = pd.DataFrame(db.collection_name.aggregate([{
        '$project': {
            '_id': 0,
            'name': '$name',
            'age': '$age',
            # Raise Sub-documents to top-level under new name
            'address_number': '$address.number',
            'address_street': '$address.street',
            'address_city': '$address.city'
        }
    }]))
    

    df:

        name  age  address_number address_street address_city
    0  Steve   27               4      Main Road       Oxford
    1   Adam   32              78        High St    Cambridge
    

    或者,如果需要手动完成的字段太多,我们也可以replaceRootmergeObjects

    df = pd.DataFrame(db.collection_name.aggregate([
        {'$replaceRoot': {'newRoot': {'$mergeObjects': ["$$ROOT", "$address"]}}},
        {'$project': {'_id': 0, 'address': 0}}
    ]))
    

    df:

        name  age  number     street       city
    0  Steve   27       4  Main Road     Oxford
    1   Adam   32      78    High St  Cambridge
    

    collection_name 设置:

    # Drop Collection if exists
    db.collection_name.drop()
    # Insert Sample Documents
    db.collection_name.insert_many([{
        'name': 'Steve', 'age': 27,
        'address': {"number": 4, "street": "Main Road", "city": "Oxford"}
    }, {
        'name': 'Adam', 'age': 32,
        'address': {"number": 78, "street": "High St", "city": "Cambridge"}
    }])
    

    【讨论】:

      猜你喜欢
      • 2016-01-25
      • 2012-10-16
      • 2013-09-06
      • 2017-10-19
      • 1970-01-01
      • 2016-08-13
      • 1970-01-01
      • 2011-11-10
      • 2021-02-28
      相关资源
      最近更新 更多