Python Numpy:加入结构化阵列? 输入
我在下面的例子中列出了很多:Python Numpy:加入结构化阵列? 输入,python,numpy,Python,Numpy,我在下面的例子中列出了很多: import numpy a1 = numpy.array([(1, 2), (3, 4), (5, 6)], dtype=[('x', int), ('y', int)]) a2 = numpy.array([(7,10), (8,11), (9,12)], dtype=[('z', int), ('w', float)]) arrays = [a1, a2] 期望输出 将它们连接在一起以创建如下统一的结构化阵列的正确方法是什么 desired_resul
import numpy
a1 = numpy.array([(1, 2), (3, 4), (5, 6)], dtype=[('x', int), ('y', int)])
a2 = numpy.array([(7,10), (8,11), (9,12)], dtype=[('z', int), ('w', float)])
arrays = [a1, a2]
期望输出
将它们连接在一起以创建如下统一的结构化阵列的正确方法是什么
desired_result = numpy.array([(1, 2, 7, 10), (3, 4, 8, 11), (5, 6, 9, 12)],
dtype=[('x', int), ('y', int), ('z', int), ('w', float)])
当前方法
这是我目前正在使用的,但速度非常慢,所以我怀疑一定有更有效的方法
from numpy.lib.recfunctions import append_fields
def join_struct_arrays(arrays):
for array in arrays:
try:
result = append_fields(result, array.dtype.names, [array[name] for name in array.dtype.names], usemask=False)
except NameError:
result = array
return result
这是一个应该更快的实现。它将所有内容转换为
numpy.uint8
数组,并且不使用任何临时变量
def join_struct_arrays(arrays):
sizes = numpy.array([a.itemsize for a in arrays])
offsets = numpy.r_[0, sizes.cumsum()]
n = len(arrays[0])
joint = numpy.empty((n, offsets[-1]), dtype=numpy.uint8)
for a, size, offset in zip(arrays, sizes, offsets):
joint[:,offset:offset+size] = a.view(numpy.uint8).reshape(n,size)
dtype = sum((a.dtype.descr for a in arrays), [])
return joint.ravel().view(dtype)
编辑:简化了代码并避免了不必要的
(
您还可以使用numpy.lib.recfunctions的合并数组
:
import numpy.lib.recfunctions as rfn
rfn.merge_arrays(arrays, flatten = True, usemask = False)
Out[52]:
array([(1, 2, 7, 10.0), (3, 4, 8, 11.0), (5, 6, 9, 12.0)],
dtype=[('x', '<i4'), ('y', '<i4'), ('z', '<i4'), ('w', '<f8')])
导入numpy.lib.rec函数作为rfn
合并数组(数组,展平=真,使用掩码=假)
出[52]:
数组([(1,2,7,10.0),(3,4,8,11.0),(5,6,9,12.0)],
dtype=[('x','还有另一种方式,可读性更强,速度更快,我认为:
def join_struct_arrays(arrays):
newdtype = []
for a in arrays:
descr = []
for field in a.dtype.names:
(typ, _) = a.dtype.fields[field]
descr.append((field, typ))
newdtype.extend(tuple(descr))
newrecarray = np.zeros(len(arrays[0]), dtype = newdtype)
for a in arrays:
for name in a.dtype.names:
newrecarray[name] = a[name]
return newrecarray
编辑:根据Sven的建议,它会变得(稍微慢一点,但实际上可读性很好):
这比我的原始解决方案更具可读性,速度快1.32倍。谢谢!这比我的原始解决方案快166倍。我自己永远也不会想到这一点。谢谢!@Jon Eric:我简化了一点代码(并将一步登天()
)。我希望这不会影响性能。也一定要看一看。@Jon Eric:你是说它快了166倍,而不是1.66倍吗?我只是想确认一下。@Hans是的,快了166倍。(当我最初测量时。)@Hans这是一种相当低级的方法,基本上只是将旧数组复制为内存块,完全忽略它们的结构。很明显,为什么可以很快完成这项工作,但要理解为什么原始解决方案如此缓慢,您需要分析代码。可能有很多原因,包括您提到的原因。很好,+1!两个建议:1.使用numpy.empty()
而不是numpy.zeros()
--无需初始化数据。2.用我的代码的最后一行替换前七行。谢谢!这确实简化了代码。但另一方面,我在IPython中使用%timeit对其进行了测试,用最后一行替换这七行,速度慢了两倍。我还将其与您的so进行了比较但是,我猜想当数组中元素的数量增加时,你的解决方案会变得更好。为了得到有意义的时间,你需要使用大数组。我希望你的解决方案至少在性能方面与我的一致。注意使用<代码>。>empty()
而不是zeros()
应该会加快速度。我认为使用dtype.descr
是错误的。根据:>警告:此属性专为符合PEP3118而存在,并且不是与np.dtype兼容的数据类型描述。
def join_struct_arrays2(arrays):
newdtype = sum((a.dtype.descr for a in arrays), [])
newrecarray = np.empty(len(arrays[0]), dtype = newdtype)
for a in arrays:
for name in a.dtype.names:
newrecarray[name] = a[name]
return newrecarray