2016-08-01 229 views
3

有沒有一種快速的方法來讀取Python中最後N行的CSV文件,使用numpypandas用numpy/pandas閱讀Python中的最後一行CSV文件

  1. 我不能做在pandasnumpyskiprowskip_header因爲該文件的長度發生變化,我將永遠需要的最後N行。

  2. 我知道我可以使用純Python從文件的最後一行逐行讀取,但這會很慢。我可以做到這一點,如果我必須,但更有效的方式與numpypandas(這實質上是使用C)將非常感激。

回答

7

用小10線測試文件,我嘗試過2種方法 - 分析整件事,然後選擇最後N行,隨負載的所有行,但只能分析過去的N:

In [1025]: timeit np.genfromtxt('stack38704949.txt',delimiter=',')[-5:] 
1000 loops, best of 3: 741 µs per loop 

In [1026]: %%timeit 
     ...: with open('stack38704949.txt','rb') as f: 
     ...:  lines = f.readlines() 
     ...: np.genfromtxt(lines[-5:],delimiter=',') 

1000 loops, best of 3: 378 µs per loop 

這被標記爲Efficiently Read last 'n' rows of CSV into DataFrame的副本。在那裏接受的答案使用

from collections import deque 

並收集該結構中的最後N行。它還使用StringIO將行提供給解析器,這是不必要的複雜化。 genfromtxt需要輸入來自它的任何行,所以行的列表就好了。

In [1031]: %%timeit 
     ...: with open('stack38704949.txt','rb') as f: 
     ...:  lines = deque(f,5) 
     ...: np.genfromtxt(lines,delimiter=',') 

1000 loops, best of 3: 382 µs per loop 

基本上與readlines和slice相同。

deque當文件非常大時可能有優勢,並且掛起到所有行上花費很大。我認爲它不會節省任何文件閱讀時間。行仍然必須逐一閱讀。

時間爲row_count其次爲skip_header的方法比較慢;它需要兩次讀取文件。 skip_header仍然需要讀取線條。

In [1046]: %%timeit 
     ...: with open('stack38704949.txt',"r") as f: 
     ...:  ...:  reader = csv.reader(f,delimiter = ",") 
     ...:  ...:  data = list(reader) 
     ...:  ...:  row_count = len(data) 
     ...: np.genfromtxt('stack38704949.txt',skip_header=row_count-5,delimiter=',') 

The slowest run took 5.96 times longer than the fastest. This could mean that an intermediate result is being cached. 
1000 loops, best of 3: 760 µs per loop 

計數行的目的,我們並不需要使用csv.reader,雖然它似乎沒有費多少額外的時間。

In [1048]: %%timeit 
     ...: with open('stack38704949.txt',"r") as f: 
     ...: lines=f.readlines() 
     ...: row_count = len(data) 
     ...: np.genfromtxt('stack38704949.txt',skip_header=row_count-5,delimiter=',') 

1000 loops, best of 3: 736 µs per loop 
3

選項1

您可以numpy.genfromtxt讀取整個文件,把它作爲一個numpy的陣列,並採取最後N行:

a = np.genfromtxt('filename', delimiter=',') 
lastN = a[-N:] 

選項2

你可以用通常的文件讀法做類似的事情:

with open('filename') as f: 
    lastN = list(f)[-N:] 

但這次你會得到最後N行的列表,作爲字符串。

選項3 - 不讀整個文件到內存

我們使用最多N次項目的列表,以保持每個迭代最後N行:

lines = [] 
N = 10 
with open('csv01.txt') as f: 
    for line in f: 
     lines.append(line) 
     if len(lines) > 10: 
      lines.pop(0) 

一個真正的CSV需要微小的變化:

import csv 
... 
with ... 
    for line in csv.reader(f): 
    ... 
2

使用參數的skiprowspandasread_csv()的土特產品另一部分是找到csv中的行數。這裏有一個可能的解決方案:

with open('filename',"r") as f: 
    reader = csv.reader(f,delimiter = ",") 
    data = list(reader) 
    row_count = len(data) 

df = pd.read_csv('filename', skiprows = row_count - N)