使用一个 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