使用numpy / pandas在Python中读取CSV文件的最后N行

时间:2016-08-01 17:38:27

标签: python csv pandas numpy

是否可以使用numpypandas快速查看Python中CSV文件的最后N行?

  1. 我无法skip_header中的numpyskiprow中的pandas,因为文件的长度不同,我总是需要最后N行。

  2. 我知道我可以使用纯Python从文件的最后一行逐行读取,但这将非常慢。如果必须,我可以这样做,但是numpypandas(基本上使用C)的更有效方式将非常受欢迎。

3 个答案:

答案 0 :(得分:7)

使用一个小的10行测试文件我尝试了两种方法 - 解析整个事物并选择最后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将行提供给解析器,这是一种不必要的复杂化。 <{1}}从任何给它行的输入中获取输入,所以行列表就可以了。

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可能会有优势,并且挂起所有线路的成本很高。我认为它不会节省任何文件读取时间。仍然必须逐行阅读。

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

答案 1 :(得分: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 :(得分:2)

使用skiprows pandas的{​​{1}}参数,更难的部分是找到csv中的行数。这是一个可能的解决方案:

read_csv()