numpy append_field为具有2d形状的新字段提供形状错误

ask*_*han 5 python numpy

我有一个结构化的numpy数组,我想使用recfunctions库 http://pyopengl.sourceforge.net/pydoc/numpy.lib.recfunctions.html 函数append_fields()或rec_append_fields()来附加一个具有某种形状的字段.但是,我收到一个错误:

ValueError:操作数无法与形状一起广播(10)(10,3)

10我现有数组的长度在哪里,是(3,)我想要追加的字段的形状.

例如:

import numpy as np
from numpy.lib.recfunctions import append_fields


my_structured_array = np.array(
    zip([0,1,2,3],[[4.3,3.2],[1.4,5.6],[6.,2.5],[4.5,5.4]]),
    dtype=[('id','int8'),('pos','2float16')]
    )
my_new_field = np.ones(
    len(my_structured_array),
    dtype='2int8'
    )
my_appended_array = append_fields(
    my_structured_array,
    'new',
    data=my_new_field
    )
Run Code Online (Sandbox Code Playgroud)

ValueError:操作数无法与形状一起广播(4)(4,2)

有任何想法吗?我尝试制作my_new_field一个元组列表,并将一个带有正确形状的dtype参数放入append_fields():

my_new_field = len(my_structured_array)*[(1,1)]

my_appended_array = append_fields(
    my_structured_array,
    'new',
    data=my_new_field,
    dtype='2int8'
    )
Run Code Online (Sandbox Code Playgroud)

但是一旦它转换为numpy数组,它似乎最终会变得相同.

当我使用rec_append_fields()而不是简单的append_fields()时,这似乎都没有改变

编辑:鉴于我的新场不具有与我的阵列相同的形状这一事实,我想@radicalbiscuit暗示我想要的追求是不可能的.

In : my_new_field.shape
Out: (4, 2)

In : my_structured_array.shape
Out: (4,)
Run Code Online (Sandbox Code Playgroud)

但是,我在数组中包含一个原始字段,其形状与原始数组不同,以表明我的观点,即字段不必具有与结构化数组相同的形状.我如何追加这样的字段?

In : my_structured_array['pos'].shape
Out: (4, 2)

In : my_new_field.shape
Out: (4, 2)
Run Code Online (Sandbox Code Playgroud)

我应该注意,对于我的应用程序,我可以附加一个空字段,只要以后可以以某种方式改变形状.谢谢!

bga*_*ari 6

append_fields()确实要求两个阵列的形状相同.话虽如此,正如你my_structured_array所知,numpy确实支持子数组(也就是说,一个字段本身可以是一个有形状的数组).

在你的情况下,我认为你可能my_new_field不希望成为二维数组,而是一个shape(my_structured_array)具有dtype元素的一维数组(形状),例如dtype([('myfield', '<i8', (2,))]).例如,

import numpy as np
from numpy.lib.recfunctions import append_fields

my_structured_array = np.array(
    zip([0,1,2,3],[[4.3,3.2],[1.4,5.6],[6.,2.5],[4.5,5.4]]),
    dtype=[('id','int8'),('pos','2float16')]
    )

my_new_field = np.ones(
    len(my_structured_array),
    dtype=[('myfield', 'i8', 2)]
    )

my_appended_array = append_fields(
    my_structured_array,
    'new',
    data=my_new_field
    )
Run Code Online (Sandbox Code Playgroud)

会屈服,

>>> my_appended_array[0]
(0, [4.30078125, 3.19921875], ([1, 1],))
Run Code Online (Sandbox Code Playgroud)

虽然数据类型myfield在嵌套时有点不方便new,

>>> my_appended_array.dtype
dtype([('id', '|i1'), ('pos', '<f2', (2,)), ('new', [('myfield', '<i8', (2,))])])
Run Code Online (Sandbox Code Playgroud)

然而,这很容易被强制剥夺,

>>> np.asarray(my_appended_array, dtype=[('id', '|i1'), ('pos', '<f2', (2,)), ('myfield', '<i8', (2,))])
array([(0, [4.30078125, 3.19921875], [0, 0]),
       (1, [1.400390625, 5.6015625], [0, 0]), (2, [6.0, 2.5], [0, 0]),
       (3, [4.5, 5.3984375], [0, 0])], 
      dtype=[('id', '|i1'), ('pos', '<f2', (2,)), ('myfield', '<i8', (2,))])
Run Code Online (Sandbox Code Playgroud)

不过,我们不得不重复my_structured_array这里的dtype有点不幸.虽然初看起来似乎numpy.lib.recfunctions.flatten_descr可以做平坦化dtype的肮脏工作,但遗憾的是它提供了元组而不是所需的列表np.dtype.然而,将其输出强制转换为列表可解决此问题,

>>> np.dtype(list(np.lib.recfunctions.flatten_descr(my_appended_array.dtype)))
dtype([('id', '|i1'), ('pos', '<f2', (2,)), ('myfield', '<i8', (2,))])
Run Code Online (Sandbox Code Playgroud)

这可以作为dtype传递给np.asarray,使得事物对于变化更加强大my_structured_array.dtype.

实际上,诸如此类的微小不一致使得与记录阵列混乱的业务.人们感觉事物可以更加连贯地融合在一起.

编辑: 事实证明,该np.lib.recfunctions.merge_arrays功能更适合这种合并,

 >>> my_appended_array = merge_arrays([my_structured_array, my_new_field], flatten=True)
 array([(0, [4.30078125, 3.19921875], [1, 1]),
        (1, [1.400390625, 5.6015625], [1, 1]), (2, [6.0, 2.5], [1, 1]),
        (3, [4.5, 5.3984375], [1, 1])], 
       dtype=[('id', '|i1'), ('pos', '<f2', (2,)), ('myfield', '<i8', (2,))])
Run Code Online (Sandbox Code Playgroud)