python - 将 C 字符串公开给 NumPy 的最快方法?

标签 python c arrays numpy cython

我正在努力将一些旧文本日志转换为 Python 中可用的格式。 文件很大,所以我正在编写自己的 C 扩展程序以尽快运行文件并使用正则表达式解析出相关字段。我的最终目标是将这些字段导出到 NumPystrings 数组中。我知道可以在 C 中将 NumPy 数组创建为 PyObject,然后在每个元素上调用 SetItem,但我希望优化尽我所能。

我可以使用 memcpyPyBuffer_FromMemory 之类的东西将 C 字符串读入 NumPy string 直接数组?我知道 NumPy 数组在内部类似于 C 数组,但我是否必须确保 NumPy 数组将被连续分配?

我打算使用 NumPy 数组构建列 Pandas 以进行统计分析。据我了解,Pandas 使用 NumPy 数组将列存储在 DataFrame 中,因此我不会从 中获得大量开销NumPyPandas。如果可能,我想避免使用 cython

最佳答案

为了让您了解字符串数组的存储方式,我将制作一个并以多种方式查看它:

In [654]: np.array(['one','two','three','four'],dtype='S5')
Out[654]: 
array([b'one', b'two', b'three', b'four'], 
      dtype='|S5')
In [655]: x=np.array(['one','two','three','four'],dtype='S5')
In [656]: x.tostring()
Out[656]: b'one\x00\x00two\x00\x00threefour\x00'
In [657]: x.view(np.uint8)
Out[657]: 
array([111, 110, 101,   0,   0, 116, 119, 111,   0,   0, 116, 104, 114,
       101, 101, 102, 111, 117, 114,   0], dtype=uint8)

因此它的数据缓冲区由 20 个字节 (4*S5) 组成。对于短于 5 的字符串,它在字节中放入(或留下)0

是的,有 C 函数可以创建给定大小和 dtype 的新数组。以及将数据 block 复制到这些数组的函数。查看 numpy 文档的 C 端,或查看其 github 存储库中的一些 numpy 代码。

关于 pandas 传输,请注意 pandas 很容易更改其列的数据类型。例如,如果您将 Nonenan 放在列中,它可能会将其更改为对象数据类型。

对象数组在数据缓冲区中存储指针。

In [658]: y=np.array(['one','two','three','four'],dtype=object)
In [659]: y
Out[659]: array(['one', 'two', 'three', 'four'], dtype=object)
In [660]: y.tostring()
Out[660]: b'\xe0\x0f\xc5\xb5\xa0\xfah\xb5\x80\x0b\x8c\xb4\xc09\x8b\xb4'

如果我解释正确,数据缓冲区有 16 个字节 - 4 个 4 字节指针。这些字符串作为常规 Python 字符串存储在内存中的其他地方(在本例中为 unicode 字符串 (Py3))。

=================

fromstringfrombuffer 让我从缓冲区重新创建数组

In [696]: x=np.array(['one','two','three','four'],dtype='S5')
In [697]: xs=x.tostring()
In [698]: np.fromstring(xs,'S5')
Out[698]: 
array([b'one', b'two', b'three', b'four'], 
      dtype='|S5')
In [700]: np.frombuffer(xs,'S5')
Out[700]: 
array([b'one', b'two', b'three', b'four'], 
      dtype='|S5')

这在不复制缓冲区的情况下工作。

但是,如果内存的不同部分有多个字符串,则从它们构建数组将需要复制到连续缓冲区中。

关于python - 将 C 字符串公开给 NumPy 的最快方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39133578/

相关文章:

c - C 结构中的箭头与点?

php - 使用单个文本框在发布后继续向数组添加值

c++ - 用于以快速且内存高效的方式处理大型数据数组的良好 C++ 数组类?

arrays - 给我 O(logd) 的算法是什么

python - has_permission() 缺少 1 个必需的位置参数 : 'view'

c++ - Gstreamer audiofirfilter

python - 如何指定 Django 测试服务器应该监听哪个 eth 接口(interface)?

在 C 中将输入数字字符串转换为整数

python Pandas : manually write to the same Excel after exporting a dataframe

python - 这是一种有效的本地化 Python 字符串格式化技术吗?