2016-08-24 61 views
3

我正在将一些旧的文本日志转换为Python中的可用格式。这些文件非常庞大,因此我正在编写自己的C扩展以尽可能快地运行文件,并使用正则表达式解析相关字段。我的最终目标是将这些字段导出为字符串的numpy数组。将C字符串暴露给numpy的最快方法是什么?

我知道可以在C中创建numpy数组作为PyObject,然后在每个元素上调用SetItem,但是我希望尽可能多地进行优化。我可以使用类似memcpy或PyBuffer_FromMemory的方式将C字符串直接读入numpy字符串数组吗?我知道numpy数组在内部类似于C数组,但是我必须确保numpy数组将连续分配吗?

我打算使用numpy数组来构建列Pandas进行统计分析。据我了解,Pandas使用numpy数组来存储数据框中的列,所以我不会有大量的开销从numpy进入Pandas。如果可能,我想避免使用cython。

+3

Python中的正则表达式不比C慢。 – Daniel

+0

是的我知道C和python之间的编译正则表达式的速度是可比的。我期望通过在C中构建numpy数组来避免其他区域的开销。 – Max

回答

3

为了举例说明如何字符串数组存储从某种意义上说,我会做出一个,并查看它在几个方面:

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) 

因此,它的DataBuffer由20个字节(4 * S5)。对于短于5的字符串,它会在该字节中放入(或离开)0

是的,有C函数用于创建给定大小和dtype的新数组。以及将数据块复制到这些数组的功能。查看numpy文档的C一面,或者查看它的github存储库上的一些numpy代码。

关于pandas转让,请注意pandas随时更改其列的dtype。例如,如果将Nonenan放在列中,可能会将其更改为对象dtype。

对象数组将指针存储在数据库中。

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' 

如果我解释是正确的,该dataBuffer有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') 

这个工作没有复制缓冲区重新创建阵列。但是,如果在内存的不同部分中有多个字符串,则从它们构建一个数组需要复制到连续的缓冲区中。

+0

感谢您提供充分的信息。我会补充说,将一个numpy的字符串数组转换成一个Object数组基本上会杀死你从numpy中获得的任何性能增益。(1)创建一个适当大小和dtype的numpy数组(2)用PyArray_BYTES在C中获取numpy数组的字节,然后(3)将我的字符串复制到那个数组中内存与memcpy。 – Max

相关问题