不丢失recarray特性的叠加numpy recarrays
假设我创建了两个具有相同数据类型的记录数组(recarray),然后把它们叠加在一起:
>>> import numpy as np
>>> dt = [('foo', int), ('bar', float)]
>>> a = np.empty(2, dtype=dt).view(np.recarray)
>>> b = np.empty(3, dtype=dt).view(np.recarray)
>>> c = np.hstack((a,b))
虽然 a
和 b
是记录数组,但 c
不是:
>>> c.foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'numpy.ndarray' object has no attribute 'foo'
>>> d = c.view(np.recarray)
>>> d.foo
array([ 0, 111050731618561, 0,
7718048, 8246760947200437872])
我当然可以像上面用 d
展示的那样,把它重新变成记录数组,但这样做不太方便。难道叠加两个记录数组不产生另一个记录数组是有原因的吗?
3 个回答
-2
13
另外,我发现了在 numpy.lib.recfunctions
中有一些辅助工具,这个模块里有一些函数可以用来合并和堆叠 recarrays
:
from numpy.lib.recfunctions import stack_arrays
c = stack_arrays((a, b), asrecarray=True, usemask=False)
c.foo
>>> array([ 140239282560000, 4376479720, -4611686018427387904,
4358733828, 4365061216])
如果你想给一个 recarray
添加额外的列,可以使用 merge_arrays
来实现:
import numpy as np
from numpy.lib.recfunctions import merge_arrays
dt1 = [('foo', int), ('bar', float)]
dt2 = [('foobar', int), ('barfoo', float)]
aa = np.empty(6, dtype=dt1).view(np.recarray)
bb = np.empty(6, dtype=dt2).view(np.recarray)
cc = merge_arrays((aa, bb), asrecarray=True, flatten=True)
type(cc)
>>> numpy.core.records.recarray
(虽然这不是问题的答案,但我把这个例子发出来作为参考)
9
我也不太清楚。很可能这是一个bug,或者是一个从来没有实现的功能。numpy.hstack
其实就是一个函数的包装器,这个函数在numpy.core.fromnumeric
里。Numeric是numpy的两个前身之一。大多数numpy的函数都有一个约定,就是输出的类型和输入的类型要一致,方法是调用输入的__array_wrap__
方法在输出上,这样得到的输出应该有相同的数据,但“包装”成了新的类。也许在numeric中没有“包装”这个概念,所以这个函数就没有添加这个功能。
你可以用这个技巧来制作一个更智能的堆叠函数。
def hstack2(arrays) :
return arrays[0].__array_wrap__(numpy.hstack(arrays))
这个方法适用于结构数组和普通数组。
>>> f = hstack2((a,b))
>>> type(f)
<class 'numpy.core.records.recarray'>
>>> f.foo
array([ 140633760262784, 111050731618561, 140633760262800,
7536928, 8391166428122670177])
>>> x = numpy.random.rand(3)
>>> y = numpy.random.rand(2)
>>> z = hstack2((x,y))
>>> type(z)
<type 'numpy.ndarray'>
我不太确定你打算怎么做,但你可能想在numpy邮件列表上问问,看看有没有比使用文档中提到的双下划线方法更好的办法,以及他们为什么不自己进行包装。