我有以下表格的数据:
#---------------------
# 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']
我有两个问题:
为什么np.genfromtxt()在导入时不删除数据头?什么时候 数据是导入的数组B仍然有标题p,q,... y 3,y 4。
为什么我们必须为标题名称提供下划线,例如Y_1, y_2等?为什么我们不能提供名称,因为它是y 1,y 2 ... y 4?
答案 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=4
为skip_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;。我不会使用参数来解决这个问题。
comments
和names
在您的情况下不合作。它可以跳过注释行,但随后会将名称行读作数据。
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