numpy:如何一次填充结构化数组中的多个字段

7
非常简单的问题:我有一个结构化数组,包含多个列,我想用另一个预先存在的数组填充其中的某些列(但不止一列)。
这是我尝试的方式:
strc = np.zeros(4, dtype=[('x', int), ('y', int), ('z', int)])
x = np.array([2, 3])
strc[['x', 'y']][0] = x

这给了我一个未来的警告:

main:1: 未来警告:Numpy 检测到您(可能)正在写入由 numpy.diagonal 或通过选择记录数组中的多个字段返回的数组。这段代码可能会在未来的 numpy 发布版本中出现问题 - 有关详细信息,请参阅 numpy.diagonal 或 arrays.indexing 参考文档。快速解决方法是进行显式复制(例如,执行 arr.diagonal().copy() 或 arr[['f0','f1']].copy())。

但即使这是一个警告,结构化数组也不会填充。到目前为止,我正在迭代两个数组,并且它可以工作,但我猜这是高度低效的。是否有更好的方法?

在Python NumPy中,结构化数组(Structured Array)和RecArray的分片赋值不会得到视图,而是产生副本。如果你需要处理的行数多于字段数,那么逐个遍历字段是完全没有问题的。网上有一个stackoverflow的问答讨论这个问题。 - hpaulj
1个回答

12
如果所有的字段具有相同的dtype,您可以创建一个视图:
import numpy as np
strc = np.zeros(4, dtype=[('x', int), ('y', int), ('z', int)])
strc_view = strc.view(int).reshape(len(strc), -1)
x = np.array([2, 3])
strc_view[0, [0, 1]] = x

如果您想要一个通用的解决方案,可以创建任何结构化数组的列视图,您可以尝试使用:

import numpy as np
strc = np.zeros(3, dtype=[('x', int), ('y', float), ('z', int), ('t', "i8")])

def fields_view(arr, fields):
    dtype2 = np.dtype({name:arr.dtype.fields[name] for name in fields})
    return np.ndarray(arr.shape, dtype2, arr, 0, arr.strides)

v1 = fields_view(strc, ["x", "z"])
v1[0] = 10, 100

v2 = fields_view(strc, ["y", "z"])
v2[1:] = [(3.14, 7)]

v3 = fields_view(strc, ["x", "t"])

v3[1:] = [(1000, 2**16)]

print strc

这里是输出结果:

[(10, 0.0, 100, 0L) (1000, 3.14, 7, 65536L) (1000, 3.14, 7, 65536L)]

谢谢HYRY,我认为你的解决方案对于我的小问题来说有点过于复杂了,但它可能对其他人有用。 - Federico Barabas

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