C-numpy:设置固定宽度字符串的数据类型?
C-numpy: Setting the data type for fixed-width strings?
我正在处理一些在 C 语言中表示为字符串的数据。我想 return 基于此数据的 numpy 数组。但是,我希望数组具有 dtype='SX',其中 X 是在运行时确定的数字。
到目前为止,我正在像这样在 C 中复制数据:
buffer_len_alt = (MAX_WIDTH)*(MAX_NUMBER_OF_ITEMS);
output_buffer = (char *) calloc(sizeof(char), buffer_len_alt);
column = PyArray_SimpleNewFromData(1, &buffer_len_alt, NPY_BYTE, output_buffer);
if (column == NULL){
return (PyObject *) NULL;
}
/* Put strings of length MAX_WIDTH in output_buffer */
return column;
如你所见,我告诉 PyArray_SimpleNewFromData,'column' 是一维字节数组,所以当我们调用 'column' 的指针变成 python对象 'col' 我们看到这个:
print(col)
>> array([48, 0, 0, 50, 48, 48, 48, 0, 0, 50, 48, 48, 50, 48, 48, 48, 0, 0], dtype=int8)
print(col.view('S3'))
>> array([b'0', b'200', b'0', b'200', b'200', b'0'], dtype='|S3')
'b' 前缀告诉我它们仍然被解释为字节数组,但我想改为使用字符串“0”、“200”等。在这个例子中,字符串是数字,但并非总是如此。
我知道我可以单独调用 b'200'.decode(format) 将每个单独的字节对象转换为字符串,但是为 numpy 编写 C 扩展的全部目的是获取所有循环 运行 在 C 中。旧的 chararray 接口(现在已弃用?)还提供了一个 array.decode 方法,可以解码数组中的每个序列,但是 numpy-C 接口 returned 的对象同样是只是普通的 ndarrays。
问题
我应该将什么 typenum 传递给 SimpleNewFromData 而不是 NPY_BYTE 以便 python 接收具有正确类型信息的数组(例如 dtype='S5')?
或者,如果没有 typenum 使用 SimpleNewFromData 实现这一点,那么我可能需要使用 SimpleNewFromDescr,但我不知道如何正确设置 PyArray_Descr 参数,并且文档在这方面确实参差不齐,所以我非常感谢任何形式的指导。
我不熟悉你代码的 C
部分,但你似乎混淆了字节字符串和 unicode 字符串的表示。 b'200'
显示表示您正在使用 Py3,其中 unicode 是默认字符串类型。
在 Py3 会话中:
原始字节:
In [482]: x=np.array([48, 0, 0, 50, 48, 48, 48, 0, 0, 50, 48, 48, 50, 48, 48, 48, 0, 0], dtype=np.int8)
查看了一个 3 字节的字符串。在 PY2 会话中,不会使用 b
。但观点是一样的。
In [483]: x.view('S3')
Out[483]:
array([b'0', b'200', b'0', b'200', b'200', b'0'],
dtype='|S3')
一个view
不改变数据缓冲区,但astype
可以根据需要转换元素,并用新的数据缓冲区创建一个新数组。
In [484]: x.view('S3').astype('U3')
Out[484]:
array(['0', '200', '0', '200', '200', '0'],
dtype='<U3')
In [485]: x.view('S3').astype('U3').view(np.uint8)
Out[485]:
array([48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 48,
0, 0, 0, 48, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 50, 0, 0, 0, 48, 0, 0, 0, 48, 0, 0, 0, 50, 0, 0,
0, 48, 0, 0, 0, 48, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0], dtype=uint8)
Unicode 版本在其缓冲区中有 72 个字节,每个字符 4 个字节。
np.char
仍然存在,但主要是将字符串方法应用于 S
和 U
类型数组。 np.char.decode
与 astype
做同样的事情。
In [489]: np.char.decode(x.view('S3'))
Out[489]:
array(['0', '200', '0', '200', '200', '0'],
dtype='<U3')
我正在处理一些在 C 语言中表示为字符串的数据。我想 return 基于此数据的 numpy 数组。但是,我希望数组具有 dtype='SX',其中 X 是在运行时确定的数字。
到目前为止,我正在像这样在 C 中复制数据:
buffer_len_alt = (MAX_WIDTH)*(MAX_NUMBER_OF_ITEMS);
output_buffer = (char *) calloc(sizeof(char), buffer_len_alt);
column = PyArray_SimpleNewFromData(1, &buffer_len_alt, NPY_BYTE, output_buffer);
if (column == NULL){
return (PyObject *) NULL;
}
/* Put strings of length MAX_WIDTH in output_buffer */
return column;
如你所见,我告诉 PyArray_SimpleNewFromData,'column' 是一维字节数组,所以当我们调用 'column' 的指针变成 python对象 'col' 我们看到这个:
print(col)
>> array([48, 0, 0, 50, 48, 48, 48, 0, 0, 50, 48, 48, 50, 48, 48, 48, 0, 0], dtype=int8)
print(col.view('S3'))
>> array([b'0', b'200', b'0', b'200', b'200', b'0'], dtype='|S3')
'b' 前缀告诉我它们仍然被解释为字节数组,但我想改为使用字符串“0”、“200”等。在这个例子中,字符串是数字,但并非总是如此。
我知道我可以单独调用 b'200'.decode(format) 将每个单独的字节对象转换为字符串,但是为 numpy 编写 C 扩展的全部目的是获取所有循环 运行 在 C 中。旧的 chararray 接口(现在已弃用?)还提供了一个 array.decode 方法,可以解码数组中的每个序列,但是 numpy-C 接口 returned 的对象同样是只是普通的 ndarrays。
问题 我应该将什么 typenum 传递给 SimpleNewFromData 而不是 NPY_BYTE 以便 python 接收具有正确类型信息的数组(例如 dtype='S5')?
或者,如果没有 typenum 使用 SimpleNewFromData 实现这一点,那么我可能需要使用 SimpleNewFromDescr,但我不知道如何正确设置 PyArray_Descr 参数,并且文档在这方面确实参差不齐,所以我非常感谢任何形式的指导。
我不熟悉你代码的 C
部分,但你似乎混淆了字节字符串和 unicode 字符串的表示。 b'200'
显示表示您正在使用 Py3,其中 unicode 是默认字符串类型。
在 Py3 会话中:
原始字节:
In [482]: x=np.array([48, 0, 0, 50, 48, 48, 48, 0, 0, 50, 48, 48, 50, 48, 48, 48, 0, 0], dtype=np.int8)
查看了一个 3 字节的字符串。在 PY2 会话中,不会使用 b
。但观点是一样的。
In [483]: x.view('S3')
Out[483]:
array([b'0', b'200', b'0', b'200', b'200', b'0'],
dtype='|S3')
一个view
不改变数据缓冲区,但astype
可以根据需要转换元素,并用新的数据缓冲区创建一个新数组。
In [484]: x.view('S3').astype('U3')
Out[484]:
array(['0', '200', '0', '200', '200', '0'],
dtype='<U3')
In [485]: x.view('S3').astype('U3').view(np.uint8)
Out[485]:
array([48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 48,
0, 0, 0, 48, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 50, 0, 0, 0, 48, 0, 0, 0, 48, 0, 0, 0, 50, 0, 0,
0, 48, 0, 0, 0, 48, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0], dtype=uint8)
Unicode 版本在其缓冲区中有 72 个字节,每个字符 4 个字节。
np.char
仍然存在,但主要是将字符串方法应用于 S
和 U
类型数组。 np.char.decode
与 astype
做同样的事情。
In [489]: np.char.decode(x.view('S3'))
Out[489]:
array(['0', '200', '0', '200', '200', '0'],
dtype='<U3')