从 JSON 文件到 Numpy 数组

Posted

技术标签:

【中文标题】从 JSON 文件到 Numpy 数组【英文标题】:From JSON file to Numpy Array 【发布时间】:2017-02-13 11:17:24 【问题描述】:

我有一个 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 Array 的回报: 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\")" 这就是文件在 RoboMongo 中的样子,我用它来可视化这个集合。 那么,'list1' 是一个字典列表。关于斜线,我不确定,但由于我最后没有使用,这并不重要。 MongoDB 以 BSON 格式存储数据,而不是普通的 json。这就是为什么那些 ObjectId 在那里的原因。不过这个问题应该没关系。 【参考方案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 个元素。 不确定您所说的不循环“数据”是什么意思。您可以做的一件事来提高速度(如果需要)是创建 numpy 数组作为您做的第一件事,然后将 mongodb 中的元素添加到该数组中。不过,我会先尝试该解决方案,以确保我过早地进行了优化。 我所说的循环数据的意思是:有没有办法在没有任何循环的情况下解决问题:for d in data【参考方案2】:

假设您已成功将该 JSON 加载到 Python 中,这是创建所需 Numpy 数组的一种方法。我的代码具有ObjectId 的最小定义,因此它不会在ObjectId 条目上引发NameError。

sorted(d["B"].items())]

从“B”字典的内容中生成(键,值)元组列表,按键排序。然后,我们仅将这些元组中的值提取到一个列表中,并将该列表附加到包含“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)

输出

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

【讨论】:

以上是关于从 JSON 文件到 Numpy 数组的主要内容,如果未能解决你的问题,请参考以下文章

将 numpy 数组列表转换为 json 以从烧瓶 api 返回

从使用 numpy.save(...) 保存的文件中将 numpy 数组加载到 C 中

将 17GB JSON 文件转换为 numpy 数组

如何从 numpy 矩阵传递到 numpy 数组?

将 Numpy 结构数组保存到 *.mat 文件

如何将 CSV 文件中的数据加载到 numpy 数组中[重复]