修改结构化数组(Python)中的多个字段?

时间:2015-02-04 03:04:52

标签: python arrays numpy

我们假设我有一个结构化数组如下:

import numpy as np
fields = [('f1', np.float32), ('f2', np.float32)]
k = np.ones(2, fields)

我希望能够访问多个字段并同时修改它们。我知道我可以使用视图访问多个字段。但我想要做的更像是以下内容,我将所有字段都修改为:

k[0] = k[0] * 2

但我收到此错误消息:

TypeError: unsupported operand type(s) for *: 'numpy.void' and 'int'

有没有人知道什么可行?越简单越好 - 我需要一些相当大的结构化数组来执行这些操作。我能想到的最好的想法是使用字段名称中的列表解析来组合k [0],将其转换为元组,并将其分配回来,但可能会有更优雅的解决方案:

k[0] = tuple([k[0][name] * 2 for name in k.dtype.names])

1 个答案:

答案 0 :(得分:0)

使用这样的dtype,有两种直接访问和修改数据的方法。按字段名称,例如k['f0'],或元组形式的元素(行)。您正在使用第二种方法。如果字段数不是那么大,并且您需要访问许多元素,那么第一个更好。

但如果字段都具有相同的数据类型,则可以在等效的2d数组上进行数学运算。

In [937]: k = np.ones(5,fields)

In [938]: k2 = np.empty((5,2),dtype=np.float32)
In [939]: k2.data = k.data  # share the data buffers
In [940]: k2 *= 2   # do math on the 2d view
In [942]: k2[0] += 3
In [943]: k    # and see the effect via the shared buffer
Out[943]: 
array([(5.0, 5.0), (2.0, 2.0), (2.0, 2.0), (2.0, 2.0), (2.0, 2.0)], 
      dtype=[('f1', '<f4'), ('f2', '<f4')])

view同样适用

In [948]: k1 = k.view(np.float32).reshape(5,2)
In [951]: k1[1] = [3,4]
In [954]: k
Out[954]: 
array([(5.0, 5.0), (3.0, 4.0), (2.0, 2.0), (2.0, 2.0), (2.0, 2.0)], 
      dtype=[('f1', '<f4'), ('f2', '<f4')])

但是使用混合dtypes,你可能必须坚持使用元组理解。

如果k有混合类型:

In [1025]: k
Out[1025]: 
array([(1.0, 1.0, b'1'), (1.0, 1.0, b'1')], 
      dtype=[('f1', '<f4'), ('f2', '<f4'), ('f3', 'S3')])

我可以使用名单列表查看浮点字段:

In [1027]: k[['f1','f2']][1]
Out[1027]: (1.0, 1.0)

但尝试使用元组修改这些字段不会做任何事情(尽管没有错误)。

In [1028]: k[['f1','f2']][1]=(2.0, 2.0)

看起来我必须一次设置一个字段,或者通过元组设置所有一个元素。

如果您需要做很多数学运算,请不要将数组分解为命名字段。