有几个假设可以解决这个问题,其中大部分与您的文档“模式”有关。根据定义的程度,即嵌套程度、预期类型和键数等,您可以采取捷径将您的集合转换为 numpy rec.array。因此,我将尝试更多地关注方法,而不是涵盖所有可能的转换案例,以便让您了解如何开始。例如,给定一个如下所示的 mongo 文档:
tdict = {'A': 151,
'B': 'somestring',
'C': [1, 2, 3],
'_id': ObjectId('4edd4e4367fbe05022000034')}
或此类文件的列表:
tlist = [{'A': 151,
'B': 'somestring',
'C': [1, 2, 3],
'_id': ObjectId('4edd4e4367fbe05022000034')},
{'A': 151,
'B': 'somestring',
'C': [1, 2, 3],
'_id': ObjectId('4edd4e4367fbe05022000034')}]
可用于将此列表转换为 numy rec.array 的函数可能如下所示:
import numpy as n
def DictToRecArray(data, columnNames=[]):
result = None
if data and isinstance(data, list) or isinstance(data, dict):
data = [data] if isinstance(data, dict) else data
if isinstance(data[0], dict):
columnNames = map(str, data[0].keys()) if not columnNames else columnNames
columns = [(str(c), type(data[0][c])) for c in columnNames]
for i,clm in enumerate(columns):
if clm[1].__name__ in ['str','unicode']:
maxlen = 0
for row in data:
maxlen = len(row[clm[0]]) if len(row[clm[0]]) > maxlen else maxlen
columns[i] = (clm[0], n.dtype('S%d' % maxlen,1))
result = n.recarray((len(data)),dtype=columns)
c_order = [c[0] for c in columns]
for i,row in enumerate(data):
for c in c_order:
result[i][c] = row[c]
return result
columnNames 允许从您的文档中选择用于生成您的rec.array 的键,并将这些键的顺序定义为rec.array 本身中的列。
如果您花一些时间查看DictToRecArray 的实现,我之前关于假设的观点就会变得很明显。例如,我可以将list 值的存在视为将文档扩展到rec.array 内的多行的机会,即对于tDict 中的键C,我可以复制键A 的值, B 和 _id 并生成形状等于 (3,) 与 (1,) 的结果 rec.array。沿着这条路走下去,您会看到DictToRecArray 的实现将与您的“模式”紧密耦合,而我的实现可能会因您的某些文档而中断。尽管如此,在这种情况下,将tlist 传递给DictToRecArray 会导致:
rec.array([(151, [1, 2, 3], 'somestring', ObjectId('4edd4e4367fbe05022000034')),
(151, [1, 2, 3], 'somestring', ObjectId('4edd4e4367fbe05022000034'))],
dtype=[('A', '<i8'), ('C', '|O8'), ('B', '|S10'), ('_id', '|O8')])
鉴于您正在寻找 data.frame 类型的结果,rec.array 应该可以很好地为您服务。希望这能让你走上正轨。