2013-02-26 46 views
9

我想讀取包含整數列表的大文本文件。 現在我做的是以下幾點:在Python中讀取輸入的最快方法

G = [] 
with open("test.txt", 'r') as f: 
    for line in f: 
     G.append(list(map(int,line.split()))) 

但是,它需要大約17秒(通過timeit)。有什麼辦法可以縮短這個時間嗎?也許,有一種不使用地圖的方法。

+0

嘗試列表理解。 – 2013-02-26 18:17:47

+4

有沒有理由不在這裏使用'numpy'? – DSM 2013-02-26 18:18:36

+3

定義「巨大」。另外,每行都有相同數量的整數嗎? – 2013-02-26 18:37:01

回答

0

最簡單的加速會去PyPy http://pypy.org/

下一個問題不能讀取所有文件(如果可能)。而是像流一樣處理它。

0

列表解析速度通常更快。

G = [[int(item) item in line.split()] for line in f] 

除此之外,嘗試PyPy以及用Cython與numpy的

+0

'G = [map(int,line.split())for line in f]'更快。 – 2013-02-26 18:41:38

+0

@StevenRumbalski這條線產生地圖對象:'[<0x0000000002D28898>處的地圖對象,<0x0000000002D28908>處的地圖對象,<0x0000000002D289B0> ...處的地圖對象'。但@forivall行可以工作。 – 2013-02-26 18:54:26

+0

@BranAlgue。啊哈!你正在使用Python 3.所以把它改成'G = [list(map(int,line.split()))for line in f]'。它仍然比嵌套列表理解更快。 – 2013-02-26 19:01:06

0

您還可以嘗試通過批量插入帶來的數據到數據庫中,然後用一組操作處理您的記錄。取決於您必須做什麼,這可能會更快,因爲批量插入軟件已針對此類任務進行了優化。

1

作爲一般的經驗法則(幾乎任何語言),使用read()來讀取整個文件將比讀取一行更快。如果您不受內存限制,請立即讀取整個文件,然後在新行上拆分數據,然後迭代行列表。

22

numpy具有功能loadtxtgenfromtxt,但都不是特別快。在廣泛分佈的庫中可用的最快速的文本閱讀器之一是read_csv函數pandashttp://pandas.pydata.org/)。在我的計算機上,每行讀取500萬行,每行包含兩個整數需要46秒,其中numpy.loadtxt,22637秒,numpy.genfromtxt,以及pandas.read_csv稍微超過1秒。

以下是顯示結果的會話。 (這是在Linux,Ubuntu的12.04 64位。你不能看到它在這裏,但該文件的每次讀取後,磁盤緩存是由一個單獨的shell中運行sync; echo 3 > /proc/sys/vm/drop_caches清除。)

In [1]: import pandas as pd 

In [2]: %timeit -n1 -r1 loadtxt('junk.dat') 
1 loops, best of 1: 46.4 s per loop 

In [3]: %timeit -n1 -r1 genfromtxt('junk.dat') 
1 loops, best of 1: 26 s per loop 

In [4]: %timeit -n1 -r1 pd.read_csv('junk.dat', sep=' ', header=None) 
1 loops, best of 1: 1.12 s per loop 
+0

+1,在我準備我的時候沒有看到你的答案。我只是對OP的版本進行了基準測試,在我的機器上需要大約16秒。我還注意到,'loadtxt'很慢。我不知道爲什麼,我預計它會更快(它應該比'genfromtxt'更快。你還使用numpy 1.7嗎? – bmu 2013-02-26 20:03:37

+0

@bmu:是的,我用numpy 1.7。 – 2013-02-26 20:05:07

+2

我打開了一個numpy問題: https://github.com/numpy/numpy/issues/3019。我無法想象,'loadtxt'太慢是很正常的。 – bmu 2013-02-26 20:16:26

5

pandas這基於numpyC基於file parser這是非常快:

# generate some integer data (5 M rows, two cols) and write it to file 
In [24]: data = np.random.randint(1000, size=(5 * 10**6, 2)) 

In [25]: np.savetxt('testfile.txt', data, delimiter=' ', fmt='%d') 

# your way 
In [26]: def your_way(filename): 
    ...:  G = [] 
    ...:  with open(filename, 'r') as f: 
    ...:   for line in f: 
    ...:    G.append(list(map(int, line.split(',')))) 
    ...:  return G   
    ...: 

In [26]: %timeit your_way('testfile.txt', ' ') 
1 loops, best of 3: 16.2 s per loop 

In [27]: %timeit pd.read_csv('testfile.txt', delimiter=' ', dtype=int) 
1 loops, best of 3: 1.57 s per loop 

所以pandas.read_csv大約需要一個半第二讀取數據和比你的方法快10倍左右。

相關問題