【问题标题】:PyArray_New or PyArray_SimpleNewFromData specify dimensions for a 3D arrayPyArray_New 或 PyArray_SimpleNewFromData 指定 3D 数组的维度
【发布时间】:2017-01-20 12:21:27
【问题描述】:

我有一个一维浮点数组(来自 C 空间),我想在 python 空间中读取它,并且副本为零。到目前为止,我所做的(主要是阅读)是:

// wrap c++ array as numpy array
//From Max http://stackoverflow.com/questions/10701514/how-to-return-numpy-array-from-boostpython
boost::python::object exposeNDarray(float * result, long size) {

    npy_intp shape[1] = { size }; // array size
    PyObject* obj = PyArray_SimpleNewFromData(1, shape, NPY_FLOAT, result);
    /*PyObject* obj = PyArray_New(&PyArray_Type, 1, shape, NPY_FLOAT, // data type
                              NULL, result, // data pointer
                              0, NPY_ARRAY_CARRAY_RO, // NPY_ARRAY_CARRAY_RO for readonly
                              NULL);*/
    handle<> array( obj );
    return object(array);
}

PyArray_New 注释部分在功能上与PyArray_SimpleNewFromData 相同。

我的问题是这个一维数组实际上应该是一个 3 维 ndarray。我可以控制我的 result 浮点数组的构造方式,如果可能的话,我希望将连续的内存块解释为 3 维数组。

我认为这可以通过指定 shape 变量来完成,但是我找不到任何关于如何解释内存的参考。

假设我需要我的数组看起来像:np.empty((x,y,z))。当我在 shape 变量中指定时,我的 result 数组的哪个部分将构成第一个维度,第二个维度的哪个部分等等?

【问题讨论】:

    标签: python c++ c numpy


    【解决方案1】:

    有描述 numpy 数组布局的文档,例如https://docs.scipy.org/doc/numpy/reference/arrays.html

    但也许一个简单的例子会有所帮助。

    让我们创建一个由 24 个整数组成的 1d 数组,并将其重塑为 3d 形状。如果 'reshape' 没有意义,您需要复习一些数组基础知识,包括 viewcopy 的概念。

    In [226]: arr = np.arange(24).reshape(2,3,4)
    In [227]: arr
    Out[227]: 
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7],
            [ 8,  9, 10, 11]],
    
           [[12, 13, 14, 15],
            [16, 17, 18, 19],
            [20, 21, 22, 23]]])
    

    查看这个数组的基本属性的一个方便的方法是这个字典:

    In [228]: arr.__array_interface__
    Out[228]: 
    {'data': (159342384, False),
     'descr': [('', '<i4')],
     'shape': (2, 3, 4),
     'strides': None,
     'typestr': '<i4',
     'version': 3}
    

    data 标识实际存储值的数据缓冲区的位置。在您的构造中,这将是您的 C 数组(或副本)。

    在这种情况下,它是一个 96 字节的缓冲区 - 每个元素 4 个字节。此缓冲区由arange 函数创建,并由reshape '重用'。

    In [229]: arr.tostring()
    Out[229]: b'\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\t\x00\x00\x00\n\x00\x00\x00\x0b\x00\x00\x00\x0c\x00\x00\x00\r\x00\x00\x00\x0e\x00\x00\x00\x0f\x00\x00\x00\x10\x00\x00\x00\x11\x00\x00\x00\x12\x00\x00\x00\x13\x00\x00\x00\x14\x00\x00\x00\x15\x00\x00\x00\x16\x00\x00\x00\x17\x00\x00\x00'
    
    In [230]: len(_)
    Out[230]: 96
    In [231]: 24*4
    

    descrarr.dtype 标识字节的解释方式 - 这里是一个 4 字节整数,'

    shapestrides 确定如何查看 1d 数组 - 在本例中为 3d 数组。

    In [232]: arr.strides
    Out[232]: (48, 16, 4)
    In [233]: arr.shape
    Out[233]: (2, 3, 4)
    

    这表示第一个维度(平面)长 48 个字节,其中有 2 个。第 2 行(每行)为 16 字节长,列元素之间的步长为 4 字节。

    通过简单地改变步幅和形状,1d 数组可以被视为 2d、3d。甚至数组转置也是通过更改shapestrides(以及另一个属性order)来实现的。

    【讨论】:

      【解决方案2】:

      您可以为此使用pybind11。实际上,您可以将 takes a c arrayreads from it 作为 numpy 视图的单元测试作为基础

      【讨论】:

      • 除非我遗漏了什么,那是一个简单的一维案例?
      • 第一个参数是shapes 的初始化列表(或/对于std::vector)。您可以为同一个连续内存数组指定另一个形状
      猜你喜欢
      • 2016-11-17
      • 2015-05-25
      • 2021-01-28
      • 2017-01-28
      • 2020-11-01
      • 1970-01-01
      • 2020-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多