numpy.genfromtxt跳过/忽略长tsv文件的最后一行

1 投票
1 回答
1282 浏览
提问于 2025-04-18 02:48

我有一个来自QuickDAQ的tsv文件,里面有三列共20万个值,我想把它导入到numpy中。问题是,使用genfromtxt的时候,它似乎漏掉了最后一行。根据我的观察,这一行并没有什么特别之处:

...
0,00232172012329102     0,0198968648910522      0,0049593448638916
0,00411009788513184     0,0142784118652344      0,00339150428771973
0,00499653816223145     0,00666630268096924     0,00308072566986084

这是一个不太成功的代码示例:

In [245]: import numpy as np

In [246]: oompa = np.genfromtxt('C_20k_73_2.tsv',delimiter='\t',usecols=(0,1,2),unpack=True,skip_header=13,dtype=str)

In [248]: oompa[1]
Out[248]: 
array(['-0,00884926319122314', '-0,00379836559295654',
   '0,000106096267700195', ..., '0,0259654521942139',
   '0,0198968648910522', '0,0142784118652344'], 
  dtype='<U21')

这个文件使用的是Windows风格的换行符,我试着在vi编辑器里去掉这些换行符,但没有什么效果。是什么原因导致genfromtxt出现这种情况?有没有办法解决这个问题,最好是不用手动编辑tsv文件?

1 个回答

1

这个文件里似乎有一些只有制表符的空行。我很惊讶 np.genfromtxt 没有报 ValueError 错误。解决这个问题的一种方法是去掉那些空的制表符行。另一种方法是在调用 np.genfromtxt 时使用 invalid_raise=False 参数:

oompa = np.genfromtxt('C_20k_73_2.tsv',delimiter='\t',
            usecols=(0,1,2),unpack=True,skip_header=13,
            dtype=str, invalid_raise=False)

这样可以跳过那些与 np.genfromtxt 预期的列数不一致的行。


如果文件不太长,查看文件最后几行的简单方法是:

print(open(filename, 'rb').read().splitlines()[:-3])

因为这个方法会打印出一个列表,所以你可以看到列表中每个项目的 repr,而不需要直接调用 repr。这个 repr 让你很容易看出哪里有制表符和换行符。

通过检查 np.genfromtxt 成功解析的最后几行的 repr,以及被跳过的前几行,你应该能找到导致问题的模式中断。


如果文件非常长,你可以使用以下方法打印最后几行:

import collections
lines = collections.deque(maxlen=2)
with open('data', 'rb') as f:
    lines.extend(f)
print(list(lines))

使用 open(filename, 'rb').read().splitlines() 的问题在于,它会把整个文件读入内存,然后把这个巨大的字符串分割成一个巨大的列表。如果文件太大,这可能会导致内存错误。deque 有一个最大元素数量,因此只要行本身不太长,就能避免这个问题。

撰写回答