有几种方法可以做到这一点:
- 阅读整个 CSV,然后使用
df.tail
- 以某种方式反转文件(对大文件执行此操作的最佳方法是什么?),然后使用
nrows
参数读取 - 以某种方式找到 CSV 中的行数,然后使用
skiprows
并读取所需的行数。 - 也许做块读取丢弃初始块(虽然不确定这将如何工作)
可以以更简单的方式完成吗?如果不是,这三者中应该优先选择哪一个,为什么?
可能相关:
无直接关系:
有几种方法可以做到这一点:
df.tail
nrows
参数读取skiprows
并读取所需的行数。可以以更简单的方式完成吗?如果不是,这三者中应该优先选择哪一个,为什么?
可能相关:
无直接关系:
我不认为 pandas 提供了一种方法来做到这一点read_csv
。
也许最整洁的(一次性)是使用collections.deque
:
from collections import deque
from StringIO import StringIO
with open(fname, 'r') as f:
q = deque(f, 2) # replace 2 with n (lines read at the end)
In [12]: q
Out[12]: deque(['7,8,9\n', '10,11,12'], maxlen=2)
# these are the last two lines of my csv
In [13]: pd.read_csv(StringIO(''.join(q)), header=None)
另一个值得尝试的选择是在第一遍中获取行数,然后再次读取文件,使用read_csv
...跳过该行数(减去 n)
这是一个方便的方法。非常适合我喜欢做的事情 -
import tailer
import pandas as pd
import io
with open(filename) as file:
last_lines = tailer.tail(file, 15)
df = pd.read_csv(io.StringIO('\n'.join(last_lines)), header=None)
您需要安装tailer才能使其正常工作:
pip install --user tailer
文件只是字节流。线不作为单独的实体存在;它们是将某些字节视为换行符的产物。因此,您必须从文件的开头读取以按顺序识别行。
如果文件不(经常)更改并且这是您需要经常执行的操作(例如,使用不同的 值n
),您可以将换行符的字节偏移量存储在第二个文件中。您可以使用这个小得多的文件和seek
命令快速跳转到第一个文件中的给定行并从那里读取。
(某些操作系统提供的面向记录的文件,其内部结构比普通平面文件更复杂。以上不适用于它们。)
由于您正在考虑反转文件,我认为可以创建新文件。
tail -n original.csv > temp.csv
head -1 original.csv | cat - temp.csv > newfile.csv && rm -f temp.csv
要求:
代码:
import pandas as pd
import io
import sys
def get_csv_tail(filepath, max_rows=1):
with open(filepath, "rb") as f:
first = f.readline().decode(sys.stdout.encoding) # Read the first line.
f.seek(-2, 2) # Jump to the second last byte.
count = 0
while count < max_rows: # Until we've gone max_rows back
try:
while f.read(1) != b"\n": # Until EOL is found...
f.seek(-2, 1) # ...jump back the read byte plus one more.
except IOError:
f.seek(-1, 1)
if f.tell() == 0:
break
count = count + 1
f.seek(-2, 1) # ...jump back the read byte plus one more.
f.seek(1, 1) # move forward one byte
tail = f.read().decode(sys.stdout.encoding) # We found our spot; read from here through to the end of the file.
f.close()
return io.StringIO(first + tail)
df = pd.read_csv(get_csv_tail('long.csv', max_rows=5)) # Get the last five rows as a df
警告:这假设您的 csv 仅在 EOL 位置包含换行符,这并非适用于所有 csv 文件。
这也会拉出标题,以便将列正确读入 pandas。如果您不需要,您可以在文件打开后删除第一行并修改函数返回以仅处理尾部。
第三个选项是我使用的:
以某种方式找到 CSV 中的行数,然后使用 skiprows 并读取所需的行数。
这是我的建议:
import pandas as pd
# User inputs
fname = 'test_file.csv'
tail_len = 15
# The two steps in the description
n_rows = sum(1 for row in open(fname, 'r'))
df = pd.read_csv(fname, skiprows=range(1, n_rows - tail_len))
关于“不知何故”,我从这里得到了这个想法。
您可以创建 metadata.csv 文件,并跟踪 csv 的长度。每次将行添加到 csv 时,使用最新的 row_count 更新 metadata.csv 文件。下次加载 csv 时,只需使用以下内容:
file_size = 139405 #stored in your metadata.csv file
n_bottom_rows = 7
df = pd.read_csv('myfile.csv',skiprows = filesize - n_bottom_rows)