从JSON文件到Numpy数组

4

我有一个MongoDB集合,通过PyMongo导入Python后,它在Python中是一个字典。 我希望将其转换为Numpy数组。

例如,如果JSON文件如下所示:

{
    "_id" : ObjectId("57065024c3d1132426c4dd53"),

    "B" : {
        "BA" : 14,
        "BB" : 23,
        "BC" : 32,
        "BD" : 41
    "A" : 50,
}
{
    "_id" : ObjectId("57065024c3d1132426c4dd53"),
    "A" : 1
    "B" : {
        "BA" : 1,
        "BB" : 2,
        "BC" : 3,
        "BD" : 4

我希望得到这个 5*2 的 Numpy 数组: np.array([[50,14,23,32,41], [1,1,2,3,4]]) 在这种情况下,第一列对应“A”,第二列对应“BA”,第三列对应“BB”,以此类推。 请注意,键名不总是以相同的顺序排序。

我的代码还没有达到预期效果(完全无法工作),它看起来像这样:

from pymongo import MongoClient
uri = "mongodb://localhost/test"
client = MongoClient(uri)
db=client.recodb
collection=db.recos

list1=list(collection.find())
array2=np.vstack([[product[key] for key in product.keys()] for product in list1])

我不了解MongoDB,但它并不是一个有效的JSON对象。它应该是一个字典列表吗?此外,'ObjectId("57065024c3d1132426c4dd53")'不是一个有效的JSON项:它应该被序列化为某种字符串,例如"ObjectId(\"57065024c3d1132426c4dd53\")" - PM 2Ring
这就是在我使用的RoboMongo中查看这个集合的文件外观。 - popuban
然后,'list1' 是一个字典列表。关于斜线,我不太确定,但是由于我没有在结尾处使用它,所以并不重要。 - popuban
MongoDB 存储数据的格式是 BSON,而不是普通的 JSON。这就是为什么会有那些 ObjectIds 的存在。不过对于这个问题来说并不重要。 - freidrichen
2个回答

1

flatdict 模块在处理MongoDB数据结构时非常有用。它可以为您处理嵌套的字典结构,使其变得扁平化:

columns = []
for d in data:
    flat = flatdict.FlatDict(d)
    del flat['_id']
    columns.append([item[1] for item in sorted(flat.items(), key=lambda item: item[0])])
np.vstack(columns)

当然,这也可以在不使用flatdict的情况下解决。

你认为在不使用循环 'data' 的情况下,能否实现这个目标?实际上,我将使用包含 14000 个元素的 'data'。 - popuban
不确定您所说的“不要在'data'上循环”。如果需要提高速度,可以做的一件事是首先创建numpy数组,然后将mongodb中的元素添加到该数组中。不过,我建议先尝试原始解决方案,确保没有过早优化。 - freidrichen
我所说的数据循环是指:是否有一种方法可以在不使用任何循环的情况下解决问题:for d in data - popuban

1
假设您已成功将JSON加载到Python中,以下是创建所需Numpy数组的一种方法。我的代码具有最小的ObjectId定义,以便在ObjectId条目上不会引发NameError错误。
sorted(d["B"].items())]

这段代码从一个"B"字典的内容中产生一个按键排序的(key, value)元组列表。然后我们仅提取这些元组中的值到一个列表中,并将该列表附加到包含"A"项值的列表中。

import numpy as np

class ObjectId(object):
    def __init__(self, objectid):
        self.objectid = objectid

    def __repr__(self):
        return 'ObjectId("{}")'.format(self.objectid)

data = [
    {
        "_id" : ObjectId("57065024c3d1132426c4dd53"),
        "B" : {
            "BA" : 14,
            "BB" : 23,
            "BC" : 32,
            "BD" : 41
        },
        "A" : 50
    },
    {
        "_id" : ObjectId("57065024c3d1132426c4dd53"),
        "A" : 1,
        "B" : {
            "BA" : 1,
            "BB" : 2,
            "BC" : 3,
            "BD" : 4
        }
    }
]

array2 = np.array([[d["A"]] + [v for _, v in sorted(d["B"].items())] for d in data])
print(array2)

output

[[50 14 23 32 41]
 [ 1  1  2  3  4]]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接