在单个文件上使用多个genfromtxt

时间:2016-01-11 19:12:23

标签: python numpy genfromtxt

我对Python很新,目前在处理输入文件读取时遇到问题。基本上我希望我的代码采用输入文件,其中相关信息包含在4行的块中。出于我的特定目的,我只关心每个区块1-3行的信息。

我正在处理的输入的两个块示例,如下所示:

#Header line 1
#Header line 2
'Mn 1',       5130.0059,  -2.765,  5.4052,  2.5,  7.8214,  1.5, 1.310, 2.390, 0.500, 8.530,-5.360,-7.630,
'  LS                                                                       3d6.(5D).4p z6F*'
'  LS                                                                       3d6.(5D).4d e6F'
'K07           A   Kurucz MnI 2007    1 K07       1 K07       1 K07       1 K07       1 K07       1 K07       1 K07       1 K07       1 K07     Mn            '
'Fe 2',       5130.0127,  -5.368,  7.7059,  2.5, 10.1221,  2.5, 1.030, 0.860, 0.940, 8.510,-6.540,-7.900,
'  LS                                                                     3d6.(3F2).4p y4F*'
'  LS                                                                           3d5.4s2 2F2'
'RU                Kurucz FeII 2013   4 K13       5 RU        4 K13       4 K13       4 K13       4 K13       4 K13       4 K13       4 K13     Fe+           '

我更愿意将这三行中的每一行的信息存储在单独的数组中。由于条目是字符串和浮点数的混合,我使用Numpy.genfromtxt来读取输入文件,如下所示:

import itertools
import numpy as np

with open(input_file) as f_in:
  #Opening file, reading every fourth line starting with line 2.
  data = np.genfromtxt(itertools.islice(f_in,2,None,4),dtype=None,delimiter=",")
  #Storing lower transition designation:
  low = np.genfromtxt(itertools.islice(f_in,3,None,4),dtype=str)
  #Storing upper transition designation:
  up = np.genfromtxt(itertools.islice(f_in,4,None,4),dtype=str)

执行代码后,genfromtxt第一次正确读取文件中的信息。但是,对于genfromtxt的第二次和第三次调用,我收到以下警告

UserWarning: genfromtxt: Empty input file: "<itertools.islice object at 0x102d7a1b0>"
warnings.warn('genfromtxt: Empty input file: "%s"' % fname)

虽然这只是一个警告,但genfromtxt的第二次和第三次调用返回的数组是空的,并且没有按预期包含字符串。如果我注释掉genfromtxt的第二次和第三次调用,代码就会按预期运行。

据我了解,上述内容应该有效,而且我有点不知道为什么不这样做。想法?

2 个答案:

答案 0 :(得分:2)

在第一个genfromtext之后(确实是islice),文件迭代器已经到达文件的末尾。因此警告和空数组:后两个islice调用使用空迭代器。

您需要将f_in.readlines()中的文件逐行读入内存,如hpaulj's answer中所示,或者在后续读取之前添加f_in.seek(0),以重置文件指针到输入的开头。这是一个对内存更友好的解决方案,如果这些文件非常庞大,这可能很重要。

# Note: Untested code follows
with open(input_file) as f_in:
    np.genfromtxt(itertools.islice(f_in,2,None,4),dtype=None,delimiter=",")

    f_in.seek(0)  # Set the file pointer back to the beginning
    low = np.genfromtxt(itertools.islice(f_in,3,None,4),dtype=str)

    f_in.seek(0)  # Set the file pointer back to the beginning
    up = np.genfromtxt(itertools.islice(f_in,4,None,4),dtype=str)

答案 1 :(得分:1)

试试这个:

with open(input_file) as f_in:
  #Opening file, reading every fourth line starting with line 2.
  lines = f_in.readlines()
  data = np.genfromtxt(lines[2::4],dtype=None,delimiter=",")
  #Storing lower transition designation:
  low = np.genfromtxt(lines[3::4],dtype=str)
  #Storing upper transition designation:
  up = np.genfromtxt(lines[4::4],dtype=str)

我没有多使用islice,但itertools往往是生成器,它会一直迭代到最后。重复打电话时要小心。您可以islicetee使用repeat。但最简单的,我认为是获得一个行列表,并选择与普通索引相关的行。

tee的示例:

with open('myfile.txt') as f:
    its = itertools.tee(f,2)
    print(list(itertools.islice(its[0],0,None,2)))
    print(list(itertools.islice(its[1],1,None,2)))

现在文件被读取一次,但可以迭代两次。