9

考虑以下简单示例:

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))

一会得到以下错误:

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

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

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

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

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

4

1 回答 1

4

问题是类型不同。"title" 是类型的一部分,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')])

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

如果要连接数据类型,则必须创建一个新的数据类型。不要错误地认为名称序列 ( x['a'], x['b']...) 构成了数组的真实维度;x以上y一维内存块数组,每个数组包含两个 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'>

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

结果是要加入单独的内存块,您实际上必须修改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')])
于 2013-09-02T13:26:40.413 回答