将文件TEST.txt结构如下:
a 45
b 45 55
c 66
当我尝试打开它时:
import numpy as np
a= np.loadtxt(r'TEST.txt',delimiter='\t',dtype=str)
我收到以下错误:
ValueError:第2行的列数错误
显然,由于第二行有三列而不是两列,但我无法使用文档找到问题的答案。
无论如何我可以修复它将所有数据保存到数组中吗?
在Matlab中我可以做类似的事情:
a=textscan(fopen('TEST.txt'),'%s%s%s');
Python中类似的东西会被贬低。
答案 0 :(得分:4)
试试np.genfromtxt
。它处理缺失的值; loadtxt
没有。比较他们的文档。
当分隔符是空格时,缺少值可能会很棘手,但是使用制表符应该没问题。如果仍有问题,请使用,
分隔符对其进行测试。
oops - 你仍然需要额外的分隔符
例如
a, 34,
b, 43, 34
c, 34
loadtxt
和genfromtxt
都接受任何逐行传递txt的迭代。所以一个简单的事情是readlines
,调整具有缺失值和分隔符的行,并将该行列表传递给加载器。或者你可以写一个'过滤器'或生成器。在以前的一些SO问题中已经描述了这种方法。
In [36]: txt=b"""a\t45\t\nb\t45\t55\nc\t66\t""".splitlines()
In [37]: txt
Out[37]: [b'a\t45\t', b'b\t45\t55', b'c\t66\t']
In [38]: np.genfromtxt(txt,delimiter='\t',dtype=str)
Out[38]:
array([['a', '45', ''],
['b', '45', '55'],
['c', '66', '']],
dtype='<U2')
我正在使用Python3,所以字节字符串标有'b'(对于宝贝和我)。
对于弦乐来说,这是过度的;但是genfromtxt
可以很容易地为每列构造一个具有不同dtypes的结构化数组。请注意,此类数组为1d,带有命名字段 - 不是编号列。
In [50]: np.genfromtxt(txt,delimiter='\t',dtype=None)
Out[50]:
array([(b'a', 45, -1), (b'b', 45, 55), (b'c', 66, -1)],
dtype=[('f0', 'S1'), ('f1', '<i4'), ('f2', '<i4')])
填充行我可以定义一个函数:
def foo(astr,delimiter=b',',cnt=3,fill=b' '):
c = astr.strip().split(delimiter)
c.extend([fill]*cnt)
return delimiter.join(c[:cnt])
并将其用作:
In [85]: txt=b"""a\t45\nb\t45\t55\nc\t66""".splitlines()
In [87]: txt1=[foo(txt[0],b'\t',3,b'0') for t in txt]
In [88]: txt1
Out[88]: [b'a\t45\t0', b'a\t45\t0', b'a\t45\t0']
In [89]: np.genfromtxt(txt1,delimiter='\t',dtype=None)
Out[89]:
array([(b'a', 45, 0), (b'a', 45, 0), (b'a', 45, 0)],
dtype=[('f0', 'S1'), ('f1', '<i4'), ('f2', '<i4')])
答案 1 :(得分:1)
如果您希望所有行的列数均相同,但有些值缺少值,则可以使用pandas轻松做到。但是您必须知道列的总数。
import pandas as pd
pd.read_csv('foo.txt', sep='\t', names=['col_a','col_b'])
答案 2 :(得分:0)
如果列数可变,则无法定义正确的np.array
形状。
如果您想将它们存储在np.array
尝试:
import numpy as np
a = np.loadtxt(r'TEST.txt', delimiter='\n', dtype=str)
现在a
是array(['a 45', 'b 45 55', 'c 66'])
。
但在这种情况下,列表更好:
with open(r'TEST.txt') as f:
a = f.read().splitlines()
现在a
是一个列表['a 45', 'b 45 55', 'c 66']