我有一个两列csv文件,举行示波器的测量:
Model,MSO4034 Firmware Version,2.48 # ... (15 lines of header) ... -5.0000000e-02,-0.0088 -4.9999990e-02,0.0116 -4.9999980e-02,0.006 -4.9999970e-02,-0.0028 -4.9999960e-02,-0.002 -4.9999950e-02,-0.0028 -4.9999940e-02,0.0092 -4.9999930e-02,-0.0072 -4.9999920e-02,-0.0008 -4.9999910e-02,-0.0056
这个数据我想加载到一个numpy数组中。 我可以使用np.loadtxt
:
np.loadtxt('data.csv', delimiter=',', skiprows=15, usecols=[1])
然而,我的数据文件是巨大的(100个MSamples),这将需要半个多小时的时间来加载和parsing(每1000行21.5毫秒)numpy。
我的首选方法是直接创build一个numpy的内存映射文件,它只是由二进制值组成,并入一个文件 。 它基本上是内存中的数组,只是它不在内存中,而是在磁盘上。
有没有方便的方法呢? 使用Linux,我可以删除头,并删除第二列,但我仍然需要parsing值的string表示,然后将其写入磁盘上的二进制文件:
$ tail -n +16 data.csv | cut -d',' -f2 -0.0088 0.0116 0.006 -0.0028 -0.002 -0.0028 0.0092 -0.0072 -0.0008 -0.0056
有没有任何Linux命令来分析浮动的string表示并将它们写在磁盘上 ?
我还建议使用Pandas的CSV解析器,但是不要一次把整个文件读入内存,而是将它在块中迭代,然后将它们写入内存映射数组中:
import numpy as np from numpy.lib.format import open_memmap import pandas as pd # make some test data data = np.random.randn(100000, 2) np.savetxt('/tmp/data.csv', data, delimiter=',', header='foo,bar') # we need to specify the shape and dtype in advance, but it would be cheap to # allocate an array with more rows than required since memmap files are sparse. mmap = open_memmap('/tmp/arr.npy', mode='w+', dtype=np.double, shape=(100000, 2)) # parse at most 10000 rows at a time, write them to the memmaped array n = 0 for chunk in pd.read_csv('/tmp/data.csv', chunksize=10000): mmap[n:n+chunk.shape[0]] = chunk.values n += chunk.shape[0] print(np.allclose(data, mmap)) # True
您可以根据一次可以放入内存中的文件大小调整块大小。 请记住,在解析块时,需要保存原始文本以及内存中已转换的值。
由于您的数据在磁盘上,因此您必须先导入它,并且代价高昂。
我认为今天最好的csv读者是pandas
。
In [7]: %timeit v=pd.read_csv('100ksamples.csv',sep=',') 1 loop, best of 3: 276 ms per loop # for 100k lines
这似乎比你的测试好10倍(但是它依赖于磁盘)。
之后,您可以使用像pickle
这样的工具以二进制模式保存并节省时间。
In [8]: %timeit with open('e.pk','bw') as f : pickle.dump(v,f) 100 loops, best of 3: 16.2 ms per loop In [9]: %timeit with open('e.pk','br') as f : v2=pickle.load(f) 100 loops, best of 3: 8.64 ms per loop