为什么在使用Python导入时没有np.genfromtxt()删除标题?

时间:2015-04-04 20:21:19

标签: python arrays numpy scipy genfromtxt

我有以下表格的数据:

#---------------------
# Data
#---------------------
p   q   r   y 1 y 2 y 3 y 4
2   8   14  748 748 748 790
2   9   22  262 245 252 328
1   5   19  512 514 511 569
2   7   19  748 748 748 805
3   11  13  160 168 108 164
2   7   20  788 788 788 848
1   4   15  310 310 310 355
3   12  17  230 210 213 218

我正在尝试使用np.genfromtxt()生成数组B,使用代码:

import numpy as np
A = open('data.dat', "r")
line = A.readline()
while line.startswith('#'):
    line = A.readline()
A_header = line.split("\t")
A_header[-1] = A_header[-1].strip()
B = np.genfromtxt('data.dat', comments='#', delimiter='\t', names = A_header, dtype = None, unpack = True).transpose()
print B
print B['y_1']

我有两个问题:

  1. 为什么np.genfromtxt()在导入时不删除数据头?什么时候 数据是导入的数组B仍然有标题p,q,... y 3,y 4。

  2. 为什么我们必须为标题名称提供下划线,例如Y_1, y_2等?为什么我们不能提供名称,因为它是y 1,y 2 ... y 4?

3 个答案:

答案 0 :(得分:2)

不是打开文件两次,而是:

import numpy as np

with open('input.txt', "r") as data:
    while True:
        line = data.readline()
        if not line.startswith('#'): break

    header = [e for e in line.strip().split('\t') if e]
    print(header)

    B = np.genfromtxt(data, names=header, dtype=None, delimiter='\t')

print B
print B['y_1']

输出:

# header
['p', 'q', 'r', 'y 1', 'y 2', 'y 3', 'y 4']

# B
[(2, 8, 14, 748, 748, 748, 790) (2, 9, 22, 262, 245, 252, 328)
 (1, 5, 19, 512, 514, 511, 569) (2, 7, 19, 748, 748, 748, 805)
 (3, 11, 13, 160, 168, 108, 164) (2, 7, 20, 788, 788, 788, 848)
 (1, 4, 15, 310, 310, 310, 355) (3, 12, 17, 230, 210, 213, 218)]

# B['y_1']
[748 262 512 748 160 788 310 230]

不是将文件名传递给np.genfromtxt,而是在这里传递data文件阅读器生成器。

否则,您会遇到skip_header无法正常工作的奇怪情况,因为它会考虑注释行。因此,当skip_header=4skip_header=1时,您必须说出np.genfromtxt(3条评论行+ 1个标题行)。

所以这种方法首先抛出""评论行。然后在下一行中提取标题。它将剩余的行传递给unpack=True函数以及相关的标题。

一些注意事项:

  • transpose() + ndarray互相取消。因此,使用两者的效果与使用两者的效果相同。所以不要使用。

  • 如果您真的想使用带空格的名称(而不是下划线)来访问字段,您可以在生成B.dtype.names = [n.replace('_', ' ') for n in B.dtype.names] print B['y 1'] # [748 262 512 748 160 788 310 230] 之后重命名字段:

    {{1}}

答案 1 :(得分:0)

您的格式正在针对genfromtxt正在做出的几个假设:

1)你有评论行和标题行(没有#字符)

2)您的列名称包含空格,genfromtxt坚持转换为_(或其他一些有效字符)。

如果我从您的示例创建一个文本文件,并用制表符替换空白(这很痛苦,特别是因为我的编辑器设置为用空格替换制表符),这有效:

In [330]: np.genfromtxt('stack29451030.txt',delimiter='\t',dtype=None,skip_header=3,names=True)
Out[330]: 
array([(2, 8, 14, 748, 748, 748, 790), (2, 9, 22, 262, 245, 252, 328)], 
      dtype=[('p', '<i4'), ('q', '<i4'), ('r', '<i4'), ('y_1', '<i4'), ('y_2', '<i4'), ('y_3', '<i4'), ('y_4', '<i4')])

我和replace_space=' '一起玩。看起来它只使用产生有效Python变量和属性名称的替换。所以'y_1'很好,但不是'y 1&#39;。我不会使用参数来解决这个问题。

commentsnames在您的情况下不合作。它可以跳过注释行,但随后会将名称行读作数据。

In [350]: np.genfromtxt('stack29451030.txt',delimiter='\t',dtype=None,comments='#')
Out[350]: 
array([['p', 'q', 'r', 'y 1', 'y 2', 'y 3', 'y 4'],
       ['2', '8', '14', '748', '748', '748', '790'],
       ['2', '9', '22', '262', '245', '252', '328']], 
      dtype='|S3')

它可以处理像#p q r y1 y2 y3 y4这样的名称行,忽略#,但它不会跳过之前的注释行。因此,如果你可以删除注释行或标题行,它可以读取它。但是看起来你必须使用comments之外的其他东西。

这看起来是最干净的负载 - 显式跳过前3行,接受标题行,然后使用jedwards's想法替换_

In [396]: A=np.genfromtxt('stack29451030.txt',delimiter='\t',dtype=None,skip_header=3,names=True)

In [397]: A.dtype.names = [n.replace('_', ' ') for n in A.dtype.names]

In [398]: A
Out[398]: 
array([(2, 8, 14, 748, 748, 748, 790), (2, 9, 22, 262, 245, 252, 328)], 
      dtype=[('p', '<i4'), ('q', '<i4'), ('r', '<i4'), ('y 1', '<i4'), ('y 2', '<i4'), ('y 3', '<i4'), ('y 4', '<i4')])

如果你不知道有多少注释行,这个生成器可以过滤掉它们:

with open('stack29451030.txt') as f:
    g = (line for line in f if not line.startswith('#'))
    A = np.genfromtxt(g, delimiter='\t', names=True, dtype=None)

genfromtxt接受任何可迭代的输入,无论是文件,行列表还是像这样的生成器。

答案 2 :(得分:0)

为了它的价值,pandas.read_table可以轻松读取此文件。

import pandas
B = pandas.read_table('data.dat', comment='#')

print B['y 1']  # Note the space is retained in the column name