genfromtxt 错误 - 得到 n 列而不是 m
genfromtxt error - Got n columns instead of m
我正在尝试使用具有 header 名称和 non-homogeneous 数据类型的 numpy 的 genfromtxt 导入数据。每次我 运行 程序都会出现错误:
Traceback (most recent call last):
raise ValueError(errmsg)
ValueError: Some errors were detected !
Line #8 (got 6 columns instead of 1)
Line #9 (got 6 columns instead of 1)
Line #10 (got 6 columns instead of 1)
Line #11 (got 6 columns instead of 1)
Line #12 (got 6 columns instead of 1)
我已经经历过这个question
但它并没有解决我的问题。这是一个非常简单的问题,但我无法弄清楚哪里出了问题。包含代码和数据:
代码
import numpy as np
data = np.genfromtxt('Data.dat', comments='#', delimiter='\t', names=True, dtype=None).transpose()
print data
Tab-separated数据
# -----
# -----
# -----
# -----
# -----
# -----
# -----
column_1 column_2 column_3 column_4 column_5 column_6
1 2 3 A 1 F
4 3 2 B 2 G
1 4 3 C 3 H
5 6 4 D 4 I
更新
简而言之,我需要的是一种将 skip_header 之后的第一个有效行转换为具有可选参数 names=True.
的第一个未注释的有效行的方法
好的,稍微戳一戳,答案就出来了。来自 genfromtxt()
文档 (http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html):
Note: There is one notable exception to this behavior: if the optional
argument names=True, the first commented line will be examined for
names.
因此,要使您的代码正常工作,您的数据应采用以下格式:
#column_1 column_2 column_3 column_4 column_5 column_6
# -----
# -----
# -----
# -----
# -----
# -----
1 2 3 A 1 F
4 3 2 B 2 G
1 4 3 C 3 H
5 6 4 D 4 I
或者,如果您有可变数量的 header/comments 行,但列都是相同的,那么您可以在 genfromtxt
参数中定义列名:
data = np.genfromtxt(
path, comments='#', delimiter='\t',
names='column_1,column_2,column_3,column_4,column_5,column_6',
dtype=None
)
但是,通过使用 comments
关键字,genfromtxt
将读取最后一个评论行之后的第一行,其中包含您的列 headers。它将假定它是数据的一部分,因此您的 dtype 应该是字符串,因此您的数据在这个阶段将如下所示:
array([('column_1', 'column_2', 'column_3', 'column_4', 'column_5', 'column_6'),
('1', '2', '3', 'A', '1', 'F'), ('4', '3', '2', 'B', '2', 'G'),
('1', '4', '3', 'C', '3', 'H'), ('5', '6', '4', 'D', '4', 'I')],
dtype=[('column_1', 'S8'), ('column_2', 'S8'), ('column_3', 'S8'), ('column_4', 'S8'), ('column_5', 'S8'), ('column_6', 'S8')])
如果您知道您的列应该是什么数据类型,您首先取一个不包括第一行的切片:
data1 = data[1:]
然后修改dtypes
:
data1.astype(np.dtype([('column_1', 'i4'),('column_2', 'i4'), ('column_3', 'i4'), ('column_4', 'S10'), ('column_5', 'i4'), ('column_6', 'S10')]))
输出:
array([(1, 2, 3, 'A', 1, 'F'), (4, 3, 2, 'B', 2, 'G'),
(1, 4, 3, 'C', 3, 'H'), (5, 6, 4, 'D', 4, 'I')],
dtype=[('column_1', '<i4'), ('column_2', '<i4'), ('column_3', '<i4'), ('column_4', 'S10'), ('column_5', '<i4'), ('column_6', 'S10')])
根据genfromtxt
的文档:
If names
is True, the field names are read from the first valid line after the first skip_header
lines.
在您的示例中,您可以将 skip_header=7
添加到 genfromtxt
调用以使其正常工作。
当 names=True
、genfromtxt
期望 第一行 行(在 skip_header
行之后)包含字段名称,即使该行是评论。显然,在注释中指定字段名称是很常见的。如果您在未注释的字段名称 之前有可变数量的注释 ,您将不得不解决 genfromtxt
的这个怪癖。以下显示了您可以执行此操作的一种方法。
这是我的测试文件。 (该文件是 space 分隔的。在对 genfromtxt
的调用中添加 delimiter='\t'
以获取制表符分隔的文件)。
In [12]: cat with_comments.dat
# Some
# comments
# here
foo bar baz
1.0 2.0 3.0
4.0 5.0 6.0
7.0 8.0 9.0
打开文件,读取行直到该行不是注释:
In [13]: f = open("with_comments.dat", "r")
In [14]: line = f.readline()
In [15]: while line.startswith('#'):
....: line = f.readline()
....:
line
现在包含字段名称行:
In [16]: line
Out[16]: 'foo bar baz\n'
将其转换为姓名列表:
In [17]: names = line.split()
将这些名称提供给 genfromtxt,然后读取文件的其余部分:
In [18]: data = genfromtxt(f, names=names)
In [19]: data
Out[19]:
array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0), (7.0, 8.0, 9.0)],
dtype=[('foo', '<f8'), ('bar', '<f8'), ('baz', '<f8')])
不要忘记关闭文件(或者更好,改用 with("with_comments.dat", "r") as f:
):
In [20]: f.close()
我正在尝试使用具有 header 名称和 non-homogeneous 数据类型的 numpy 的 genfromtxt 导入数据。每次我 运行 程序都会出现错误:
Traceback (most recent call last):
raise ValueError(errmsg)
ValueError: Some errors were detected !
Line #8 (got 6 columns instead of 1)
Line #9 (got 6 columns instead of 1)
Line #10 (got 6 columns instead of 1)
Line #11 (got 6 columns instead of 1)
Line #12 (got 6 columns instead of 1)
我已经经历过这个question 但它并没有解决我的问题。这是一个非常简单的问题,但我无法弄清楚哪里出了问题。包含代码和数据:
代码
import numpy as np
data = np.genfromtxt('Data.dat', comments='#', delimiter='\t', names=True, dtype=None).transpose()
print data
Tab-separated数据
# -----
# -----
# -----
# -----
# -----
# -----
# -----
column_1 column_2 column_3 column_4 column_5 column_6
1 2 3 A 1 F
4 3 2 B 2 G
1 4 3 C 3 H
5 6 4 D 4 I
更新
简而言之,我需要的是一种将 skip_header 之后的第一个有效行转换为具有可选参数 names=True.
的第一个未注释的有效行的方法好的,稍微戳一戳,答案就出来了。来自 genfromtxt()
文档 (http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html):
Note: There is one notable exception to this behavior: if the optional argument names=True, the first commented line will be examined for names.
因此,要使您的代码正常工作,您的数据应采用以下格式:
#column_1 column_2 column_3 column_4 column_5 column_6
# -----
# -----
# -----
# -----
# -----
# -----
1 2 3 A 1 F
4 3 2 B 2 G
1 4 3 C 3 H
5 6 4 D 4 I
或者,如果您有可变数量的 header/comments 行,但列都是相同的,那么您可以在 genfromtxt
参数中定义列名:
data = np.genfromtxt(
path, comments='#', delimiter='\t',
names='column_1,column_2,column_3,column_4,column_5,column_6',
dtype=None
)
但是,通过使用 comments
关键字,genfromtxt
将读取最后一个评论行之后的第一行,其中包含您的列 headers。它将假定它是数据的一部分,因此您的 dtype 应该是字符串,因此您的数据在这个阶段将如下所示:
array([('column_1', 'column_2', 'column_3', 'column_4', 'column_5', 'column_6'),
('1', '2', '3', 'A', '1', 'F'), ('4', '3', '2', 'B', '2', 'G'),
('1', '4', '3', 'C', '3', 'H'), ('5', '6', '4', 'D', '4', 'I')],
dtype=[('column_1', 'S8'), ('column_2', 'S8'), ('column_3', 'S8'), ('column_4', 'S8'), ('column_5', 'S8'), ('column_6', 'S8')])
如果您知道您的列应该是什么数据类型,您首先取一个不包括第一行的切片:
data1 = data[1:]
然后修改dtypes
:
data1.astype(np.dtype([('column_1', 'i4'),('column_2', 'i4'), ('column_3', 'i4'), ('column_4', 'S10'), ('column_5', 'i4'), ('column_6', 'S10')]))
输出:
array([(1, 2, 3, 'A', 1, 'F'), (4, 3, 2, 'B', 2, 'G'),
(1, 4, 3, 'C', 3, 'H'), (5, 6, 4, 'D', 4, 'I')],
dtype=[('column_1', '<i4'), ('column_2', '<i4'), ('column_3', '<i4'), ('column_4', 'S10'), ('column_5', '<i4'), ('column_6', 'S10')])
根据genfromtxt
的文档:
If
names
is True, the field names are read from the first valid line after the firstskip_header
lines.
在您的示例中,您可以将 skip_header=7
添加到 genfromtxt
调用以使其正常工作。
当 names=True
、genfromtxt
期望 第一行 行(在 skip_header
行之后)包含字段名称,即使该行是评论。显然,在注释中指定字段名称是很常见的。如果您在未注释的字段名称 之前有可变数量的注释 ,您将不得不解决 genfromtxt
的这个怪癖。以下显示了您可以执行此操作的一种方法。
这是我的测试文件。 (该文件是 space 分隔的。在对 genfromtxt
的调用中添加 delimiter='\t'
以获取制表符分隔的文件)。
In [12]: cat with_comments.dat
# Some
# comments
# here
foo bar baz
1.0 2.0 3.0
4.0 5.0 6.0
7.0 8.0 9.0
打开文件,读取行直到该行不是注释:
In [13]: f = open("with_comments.dat", "r")
In [14]: line = f.readline()
In [15]: while line.startswith('#'):
....: line = f.readline()
....:
line
现在包含字段名称行:
In [16]: line
Out[16]: 'foo bar baz\n'
将其转换为姓名列表:
In [17]: names = line.split()
将这些名称提供给 genfromtxt,然后读取文件的其余部分:
In [18]: data = genfromtxt(f, names=names)
In [19]: data
Out[19]:
array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0), (7.0, 8.0, 9.0)],
dtype=[('foo', '<f8'), ('bar', '<f8'), ('baz', '<f8')])
不要忘记关闭文件(或者更好,改用 with("with_comments.dat", "r") as f:
):
In [20]: f.close()