将任何字典转换为结构化数组

时间:2018-01-04 22:17:54

标签: python python-2.7 numpy

我正在尝试生成一个结构化numpy数组,该数组从字典中获取字段名称和变量类型。我希望它能够处理用户可以投入的大部分内容。

目前它的工作原理如下:

>>> d = dict( a=0.456, b=1234.5687020, c=4, d=np.arange(3), text='text')
>>> dtype = [(str(key), val.__class__) for key, val in d.iteritems()]     
>>> arr = np.zeros( (5,), dtype=dtype)
>>> arr
array([(0.0, '', 0, 0.0, 0), (0.0, '', 0, 0.0, 0), (0.0, '', 0, 0.0, 0),
   (0.0, '', 0, 0.0, 0), (0.0, '', 0, 0.0, 0)], 
  dtype=[('a', '<f8'), ('text', 'S'), ('c', '<i8'), ('b', '<f8'), ('d', 'O')])

到目前为止一切顺利。但是我现在尝试将示例字典的内容分配给第一个元素,这并不是很好:

>>> for key, val in d.iteritems():
...     arr[0][str(key)] = val

>>> arr[0]
(0.456, '', 4, 1234.5687020, [0, 1, 2])

数字和数组看起来没问题,但文字丢失了。有趣的是,手动分配到文本字段会产生不同的结果:

>>> arr[0]['text'] = 'text'
>>> arr[0]['text'] 
't'

我发现这很难理解......

我确定类型的方法似乎选择了一种过于严格的类型。我期望用float32初始化然后分配float64会减少数据丢失,但我至少期望数组能够保存示例数据。

是否有更强大(可能更优雅?)的方式来确定dtype哪些字符串能够正常工作?

我所寻找的是一种确定字典内容类型的强大方法。如果我需要要求输入字典中的文本定义最大字符串长度,这是可以接受的,但我的函数事先不知道它将获得哪些键和类型。

2 个答案:

答案 0 :(得分:1)

您需要为S类型提供长度:

dtype = [('a', float), ('b', float), ('c', int), ('d', numpy.ndarray), ('text', 'S10')]
arr = np.zeros( (5,), dtype=dtype)
for key, val in d.items():
    arr[0][str(key)] = val

现在:

>>> arr[0]
( 0.456,  1234.56870202, 4, array([0, 1, 2]), b'text')

答案 1 :(得分:0)

我设法提出的最佳“自动解决方案是使用由每个元素制作的SELECT qryReadMeRequired.ID, tblReadMeRecord.ReadDate FROM tblReadMeRecord RIGHT JOIN qryReadMeRequired ON (tblReadMeRecord.DocumentID = qryReadMeRequired.DocumentID) AND (tblReadMeRecord.PersonID = qryReadMeRequired.ID) WHERE (((tblReadMeRecord.ReadDate) Is Null)) np数组,而不是dtype属性:

__class__

这将文本输入限制为示例数据中包含的内容的长度,如果任何输入是一个numpy数组,则会失败(如上所示 - 它将数组分类为>>> dtype = [(str(key), np.array([val]).dtype) for key, val in d.iteritems()] >>> dtype [('a', dtype('float64')), ('text', dtype('S4')), ('c', dtype('int64')), ('b', dtype('float64')), ('d', dtype('int64'))] >>> arr = np.zeros( (5,), dtype=dtype) >>> for key, val in d.iteritems(): ... arr[0][str(key)] = val ... >>> arr[0] (0.456, 'text', 4, 1234.568702020934, 0) ,因为它的元素是)。

我最终做的是编译一个单独的列表,列出所有字符串,然后手动将它们添加到dtype中,如int

'S128'

不那么优雅,我想我可以手动捕捉其他一些类型,但至少它有效。

我真的希望有一个表达式可以自动生成一个可以正常工作的类型。我仍然不明白为什么上面的循环根本没有分配字符串变量,虽然直接赋值确实分配了一些东西......