gpt4 book ai didi

python - 通过 C-API 访问 Numpy Recarray

转载 作者:太空狗 更新时间:2023-10-29 21:53:11 25 4
gpt4 key购买 nike

如果我们有一个 Numpy recarray: x = np.array([(1.,2.)], dtype=np.dtype([('a','<f8'),('b','<f8')]))
我们可以在 Python 中访问它的字段:
x['a']x['b']
但是如果这个数组作为 PyArrayObject 传递给 C 程序我们如何访问它的字段?
我知道我们可以通过以下方式在 C 中获取数据类型:PyArray_Descr *dtype = PyArray_DTYPE(arr)
PyObject *fields = dtype->fields但是如何使用它来访问 x['a'] 处的数据? ?

最佳答案

我会尝试回答我自己的问题。
看来您可以使用函数 PyObject_GetItem()访问 Numpy recarray 中的字段。为了对此进行测试,我创建了一个包含三个字段的简单 recarray:
np.dtype([('field1', '<f8', (1,2)), ('field2', '<f8', (2,2)), ('field3', '<f8', (3,1))])
我将这个数组发送到我的 C++ 函数并执行两个循环:一个循环遍历每个字段,一个嵌套循环遍历每个字段中的数组元素(例如 x['field1'], x['field2'], x['field3'])。在外循环中我使用 PyObject_GetItem()访问每个字段。代码如下:

C++ 代码

#include "Python.h"
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "arrayobject.h"
#include <cmath>
#include <iostream>
#include <iomanip>
using namespace std;

static PyObject *readarray(PyObject *self, PyObject *args) {
PyArrayObject *arr, *x2;
PyArray_Descr *dtype;
PyObject *names, *name, *x1 = NULL;
Py_ssize_t N, i;
NpyIter *iter;
NpyIter_IterNextFunc *iternext;
double **dataptr;
npy_intp index;

if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &arr)) {
return NULL;
}
dtype = PyArray_DTYPE(arr);
names = dtype->names;
if (names != NULL) {
names = PySequence_Fast(names, NULL);
N = PySequence_Fast_GET_SIZE(names);
for (i=0; i<N; i++) {
name = PySequence_Fast_GET_ITEM(names, i);
cout << setw(7) << left << PyString_AsString(name);
x1 = PyObject_GetItem((PyObject *) arr, name);
x2 = (PyArrayObject *) x1;
dtype = PyArray_DTYPE(x2);
iter = NpyIter_New(x2, NPY_ITER_READONLY, NPY_KEEPORDER, NPY_SAME_KIND_CASTING, dtype);
if (iter == NULL) {return NULL;}
dataptr = (double **) NpyIter_GetDataPtrArray(iter);
iternext = NpyIter_GetIterNext(iter, NULL);
do {
index = NpyIter_GetIterIndex(iter);
if (index==0) {
cout << setw(6) << right << index << setw(9) << setiosflags(ios::fixed) << setprecision(4) <<**dataptr << endl;
} else {
cout << " " << setw(6) << right << index << setw(9) << setiosflags(ios::fixed) << setprecision(4) << **dataptr << endl;
}
} while (iternext(iter));
}
NpyIter_Deallocate(iter);
}
return Py_BuildValue("i", 0);
}

static PyMethodDef pyproj4methods[] = {
{"readarray", readarray, METH_VARARGS, "Documentation"},
{NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC initpyproj4(void) {
Py_InitModule("pyproj4", pyproj4methods);
import_array();
}


Python 代码

import numpy as np
import pyproj4 as p4
np.random.seed(22)

## Python Implementation ##
dt = np.dtype([('field1', '<f8', (1,2)), ('field2', '<f8', (2,2)), ('field3', '<f8', (3,1))])
x = np.zeros(2, dtype=dt)

for name in x.dtype.names:
m,n,p = x[name].shape
x[name] = np.random.randn(m,n,p)
it = np.nditer(x[name], ['c_index'], ['readonly'])
for num in it:
if it.index==0:
print '{0:6s} {1:6d} {2: 2.4f}'.format(name, it.index, num.item())
else:
print '{0:6s} {1:6d} {2: 2.4f}'.format(' ', it.index, num.item())
print '-----------------------'
## C-API Implementation ##
p4.readarray(x)


两种情况下的输出如下所示:

field1      0  -0.0919
1 -1.4634
2 1.0818
3 -0.2393
field2 0 -0.4911
1 -1.0023
2 0.9188
3 -1.1036
4 0.6265
5 -0.5615
6 0.0289
7 -0.2308
field3 0 0.5878
1 0.7523
2 -1.0585
3 1.0560
4 0.7478
5 1.0647

如果您知道更好的方法来完成此任务,请不要犹豫发布您的解决方案。

关于python - 通过 C-API 访问 Numpy Recarray,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19124072/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com