我经常处理包含几列(通常少于 10 列)和多达数千万行的 ascii 表。他们看起来像
176.792 -2.30523 0.430772 32016 1 1 2
177.042 -1.87729 0.430562 32016 1 1 1
177.047 -1.54957 0.431853 31136 1 1 1
...
177.403 -0.657246 0.432905 31152 1 1 1
我有许多读取、操作和保存文件的 python 代码。我一直使用numpy.loadtxt
并numpy.savetxt
做到这一点。但numpy.loadtxt
至少需要 5-6Gb RAM 才能读取 1Gb ascii 文件。
昨天我发现了 Pandas,它几乎解决了我所有的问题:pandas.read_table
同时numpy.savetxt
将我的脚本的执行速度(2 个)提高了 3 或 4 倍,同时非常节省内存。
一切都很好,直到我尝试读取开头包含一些注释行的文件。文档字符串 (v=0.10.1.dev_f73128e) 告诉我不支持行注释,这可能会出现。我认为这会很棒:我真的很喜欢在numpy.loadtxt
. 对这将如何变得可用有任何想法吗?有可能跳过这些行也很好(文档声明它们将作为empy返回)
不知道我的文件中有多少注释行(我处理了来自不同人的数千条注释),现在我打开文件,计算文件开头以注释开头的行数:
def n_comments(fn, comment):
with open(fname, 'r') as f:
n_lines = 0
pattern = re.compile("^\s*{0}".format(comment))
for l in f:
if pattern.search(l) is None:
break
else:
n_lines += 1
return n_lines
接着
pandas.read_table(fname, skiprows=n_comments(fname, '#'), header=None, sep='\s')
有没有更好的方法(可能在熊猫中)来做到这一点?
最后,在发布之前,我查看了一些代码pandas.io.parsers.py
以了解pandas.read_table
引擎盖下的工作原理,但我迷路了。谁能指出我实现文件读取的地方?
谢谢
EDIT2:我想得到一些改进,摆脱if
@ThorstenKranz 的第二个实现中的一些FileWrapper
,但几乎没有得到任何改进
class FileWrapper(file):
def __init__(self, comment_literal, *args):
super(FileWrapper, self).__init__(*args)
self._comment_literal = comment_literal
self._next = self._next_comment
def next(self):
return self._next()
def _next_comment(self):
while True:
line = super(FileWrapper, self).next()
if not line.strip()[0] == self._comment_literal:
self._next = self._next_no_comment
return line
def _next_no_comment(self):
return super(FileWrapper, self).next()