python:numpy:命名数组的连接

Han*_*art 9 python numpy

考虑以下简单示例:

x = numpy.array([(1,2),(3,4)],dtype=[('a','<f4'),('b','<f4')])
y = numpy.array([(1,2),(3,4)],dtype=[('c','<f4'),('d','<f4')])
numpy.hstack((x,y))
Run Code Online (Sandbox Code Playgroud)

一个将收到以下错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python33\lib\site-packages\numpy\core\shape_base.py", line 226, in vstack
    return _nx.concatenate(list(map(atleast_2d,tup)),0)
TypeError: invalid type promotion
Run Code Online (Sandbox Code Playgroud)

如果数组没有标题它可以工作

x = numpy.array([(1,2),(3,4)],dtype='<f4')
y = numpy.array([(1,2),(3,4)],dtype='<f4')
numpy.hstack((x,y))
Run Code Online (Sandbox Code Playgroud)

如果我从x和y中删除名称,它也可以.

问题:如何连接,标题为numpy数组的vstack或hstack?注意:numpy.lib.recfunctions.stack_arrays也不能正常工作

sen*_*rle 4

问题是类型不同。“标题”是类型的一部分,并且y使用与 不同的名称x,因此类型不兼容。如果您使用兼容类型,则一切正常:

>>> x = numpy.array([(1, 2), (3, 4)], dtype=[('a', '<f4'), ('b', '<f4')])
>>> y = numpy.array([(5, 6), (7, 8)], dtype=[('a', '<f4'), ('b', '<f4')])
>>> numpy.vstack((x, y))
array([[(1.0, 2.0), (3.0, 4.0)],
       [(5.0, 6.0), (7.0, 8.0)]], 
      dtype=[('a', '<f4'), ('b', '<f4')])
>>> numpy.hstack((x, y))
array([(1.0, 2.0), (3.0, 4.0), (5.0, 6.0), (7.0, 8.0)], 
      dtype=[('a', '<f4'), ('b', '<f4')])
>>> numpy.dstack((x, y))
array([[[(1.0, 2.0), (5.0, 6.0)],
        [(3.0, 4.0), (7.0, 8.0)]]], 
      dtype=[('a', '<f4'), ('b', '<f4')])
Run Code Online (Sandbox Code Playgroud)

有时dstack,等足够聪明,可以以合理的方式强制类型,但numpy无法知道如何将记录数组与不同的用户定义的字段名称组合起来。

如果你想连接数据类型,那么你必须创建一个新的数据类型。不要错误地认为名称序列 ( x['a'], x['b']...) 构成了数组的真实维度;xy上面是内存块的一维数组,每个内存块包含两个 32 位浮点数,可以使用名称'a'和进行访问'b'。但正如您所看到的,如果您访问数组中的单个项目,您不会像它确实是第二维那样获得另一个数组。您可以在这里看到差异:

>>> x = numpy.array([(1, 2), (3, 4)], dtype=[('a', '<f4'), ('b', '<f4')])
>>> x[0]
(1.0, 2.0)
>>> type(x[0])
<type 'numpy.void'>

>>> z = numpy.array([(1, 2), (3, 4)])
>>> z[0]
array([1, 2])
>>> type(z[0])
<type 'numpy.ndarray'>
Run Code Online (Sandbox Code Playgroud)

这就是允许记录数组包含异构数据的原因;记录数组可以包含字符串和整数,但代价是您无法ndarray在单个记录级别获得 an 的全部功能。

结果是,要连接各个内存块,您实际上必须修改数组的dtype。有几种方法可以做到这一点,但我能找到的最简单的方法涉及鲜为人知的numpy.lib.recfunctions库(我看到你已经找到了!):

>>> numpy.lib.recfunctions.rec_append_fields(x, 
                                             y.dtype.names, 
                                             [y[n] for n in y.dtype.names])
rec.array([(1.0, 2.0, 1.0, 2.0), (3.0, 4.0, 3.0, 4.0)], 
      dtype=[('a', '<f4'), ('b', '<f4'), ('c', '<f4'), ('d', '<f4')])
Run Code Online (Sandbox Code Playgroud)