我已经有了一个包含300000多行的python字符串的表,如下所示:
123 1 2.263E-04 2.024E+00 8.943E+03 9.030E+02 2.692E+03 5.448E+03 3.816E-01 1.232E-01 0.000E+00 4.389E+02 1.950E+02
如果有帮助,则使用以下Fortran格式语句生成此表:
^{pr2}$我想看看我能不能比熊猫.read_csv(…,delim廑whitespace=True)这对我来说需要540ms。在
text = r''' 372 1 0.000E+00 0.000E+00 0.000E+00 9.150E+02 3.236E+03 0.000E+00 0.000E+00 0.000E+00 0.000E+00 0.000E+00 3.623E+02\n'''*300000
%timeit df = pd.read_csv(StringIO(text), delim_whitespace=True, header=None)
产量:
549 ms ± 3.42 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
我认为知道行长度和列宽可以使read_fwf
更快,但显然优化程度较低:
widths = [5]*2 + [11]*11
%timeit df = pd.read_fwf(StringIO(text), widths=widths, header=None)
产量:
2.95 s ± 29 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
这是不是可以用Cython做得更快?我很少使用C或Cython,所以很遗憾,我甚至不知道从哪里开始使用一个初始示例。我也对f2py之类的东西持开放态度,但前提是它值得为Cython而烦恼。我的依赖关系中已经有了一些numba和Cython的东西,所以我对Cython的解决方案更加开放。我知道numba不处理文本,所以它对这个没有帮助。在
感谢所有能帮忙的人!在
我想出了一个满足我需要的Cython解决方案。这是使用Cython cell magic for Jupyter notebook来处理编译。我选择2000000作为数组初始化,因为这是我的数据的合理上限。函数只返回numpy数组中实际填充的行。然后将numpy数组传递到pandas数据帧是相当便宜的。在
我不确定还有多少优化可以做,因为我实际上也抛出了一些垃圾行,我认为这排除了内存映射。我可以使用类似于an answer to another question I had中的指针,但是如果我移动指针而不是迭代行,那么在我的文件中查找数据并检测坏行(有关读取数据页的更大问题,请参见下面的更多内容)。在
通过这个,我可以运行以下内容:
^{pr2}$得到这个结果:
^{3}$为了比较和完整,我还编写了一个快速的纯python版本:
它用了1.15秒:
然后,我尝试将其应用到一个非常简单的Cython示例中,该示例在717毫秒内运行:
然后我就崩溃了,找到了上面更优化的Cython版本。在
就在那时,我意识到Cython可以更有效地解决这个问题和一个缓慢的regex问题。我使用regex查找并捕获大约5000页的数据,然后将这些数据连接到我要读取的表中。下面显示了更接近我实际的Cython函数。它处理查找数据页、捕获页级详细信息(时间),然后读取实际数据行,直到检测到停止标志(以0或1开头的行)。我的regex只是为了提取我想要的数据而占用了1s的时间,所以总体来说这节省了我很多时间。在
相关问题 更多 >
编程相关推荐