2016-08-01 225 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)