【问题标题】:genfromtxt error - Got n columns instead of mgenfromtxt 错误 - 得到 n 列而不是 m
【发布时间】:2015-03-02 13:57:40
【问题描述】:

我正在尝试使用带有标题名称和非同质数据类型的 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

制表符分隔的数据

# -----
# -----
# -----
# -----
# -----
# -----
# -----
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 的第一个未注释的有效行的方法。

【问题讨论】:

  • 您的列标题是制表符分隔的吗?它们可能是空格分隔的,这导致 numpy 将其解释为一列。
  • 这里看起来是空格分隔的,但实际上是制表符分隔的。

标签: python numpy genfromtxt


【解决方案1】:

names=True 时,genfromtxt 期望 第一 行(skip_header 行之后)包含字段名称,即使该行是注释。显然,在注释中指定字段名称是很常见的。如果您在未注释的字段名称​​之前有可变数量的 cmets,则您必须解决 genfromtxt 的这个怪癖。以下显示了您可以执行此操作的一种方法。

这是我的测试文件。 (该文件以空格分隔。在对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()

【讨论】:

  • 你是怎么逃出来的[19]?现在,如何将结构化数组转换为 numpy 数组?
  • 我不确定您所说的“离开[19]”是什么意思。这只是显示data 的值。 (当我做这个例子时,我在 ipython (ipython.org) shell 中工作。)关于将结构化数组(is numpy 数组)转换为“numpy 数组”的问题应该是新问题。但是先搜索类似的问题——以前有人问过。
【解决方案2】:

根据genfromtxt的文档:

如果names 为True,则从第一行skip_header 之后的第一个有效行读取字段名称。

在您的示例中,您可以将 skip_header=7 添加到 genfromtxt 调用中以使其工作。

【讨论】:

  • 我根据数据文件有可变的注释行,换句话说,跳过标题值是可变的。我有5000多个文件,用这种方法是不可能的。
【解决方案3】:

好的,稍微刺激一下已经揭示了答案。来自genfromtxt() 文档 (http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html):

注意:此行为有一个值得注意的例外:如果可选 参数名称=真,将检查第一个注释行 名字。

因此,为了使您的代码正常工作,您的数据应采用以下格式:

#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

或者,如果您有可变数量的标题/cmets 行,但列都是相同的,那么您可以在 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 将读取包含列标题的最后一个评论行之后的第一行。它将假定它是数据的一部分,因此您的 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')])

【讨论】:

  • 您可以使用@mkrieger1 建议的skip_header=7 关键字。
  • @nxkryptor,修改答案以解决您的数据格式。
猜你喜欢
  • 2021-10-29
  • 1970-01-01
  • 2017-01-22
  • 1970-01-01
  • 2018-04-26
  • 2019-08-20
  • 2014-06-14
  • 1970-01-01
  • 2023-03-19
相关资源
最近更新 更多