numpy.genfromtxt- ValueError- Line#(得到n列代替m)

时间:2016-09-14 20:34:50

标签: python numpy genfromtxt

所以,我一直在编写代码来读取文件中的数据集并将其分开进行分析。

有问题的数据是从.dat文件中读取的,如下所示:

14        HO2       O3        OH        O2        O2
15        HO2       HO2       H2O2      O2
16        H2O2      OH        HO2       H2O
17        O         O         O2
18        O         O2        O3
19        O         O3        O2        O2

我写的代码看起来像这样:

edge_data=np.genfromtxt('Early_earth_reaction.dat', dtype = str, 
missing_values=True, filling_values=bool)

计划是我然后运行数据集中的值并从中构建配对列表。

edge_list=[]
for i in range(360):
    edge_list.append((edge_data[i,0],edge_data[i,2]))
    edge_list.append((edge_data[i,1],edge_data[i,2]))
    print edge_data[i,0]
    if edge_data[i,3] != None:
        edge_list.append((edge_data[i,0],edge_data[i,3]))
        edge_list.append((edge_data[i,1],edge_data[i,3]))
    if edge_data[i,4]!= None:
        edge_list.append((edge_data[i,0],edge_data[i,4]))
        edge_list.append((edge_data[i,1,edge_data[i,4]))

然而,在运行它时,我收到错误消息

File "read_early_earth.py", line 52, in main
edge_data=np.genfromtxt('Early_earth_reaction.dat', dtype = str,  
usecols=(1,2,3,4,5), missing_values=True, filling_values=bool)
File "/usr/lib/python2.7/dist-packages/numpy/lib/npyio.py", line 1667, 
in genfromtxt
raise ValueError(errmsg)
ValueError: Some errors were detected !
Line #6 (got 4 columns instead of 5)
Line #14 (got 6 columns instead of 5)
Line #17 (got 4 columns instead of 5)

依此类推。据我所知,这种情况正在发生,因为有些行并不是所有的列都有值,这显然会为循环抛出numpy。

在numpy中有解决方法吗?或者,还有另一种方法可以完成这项任务吗?我知道,更糟糕的是,我可以折磨一些正则表达式来完成这项工作,但我更喜欢一种方法,如果可能的话,它会更有效率。

谢谢!

2 个答案:

答案 0 :(得分:2)

您似乎已经阅读了有关缺失值的genfromtxt。它是否说明了分隔符的使用?

我认为它可以用

这样的行来处理缺失值
'one, 1, 234.4, , ,'
'two, 3, , 4, 5'

但是当分隔符是默认的'白色空间'它不能。阅读一行后的第一步是

 strings = line.split(delimiter)

如果len(strings)与初始目标不匹配,则为对象。显然,它不会猜测你想填充n-len(strings)缺少值的行。

想到的选项:

  • 尝试熊猫;它可能会更加努力地猜测你的意图

  • 写自己的读者。熊猫编译; genfromtxt是简单的Python。它逐行读取文件,拆分并转换字段,并将列表附加到主列表。它最后将该列表列表转换为数组。你自己的读者应该同样有效率。

  • 预处理文件以添加缺失值或更改分隔符。 genfromtxt接受任何为其提供线条的内容。所以它适用于字符串列表,产生修改行的文件阅读器等。这可能是最简单的。

    def foo(astr):     个STR = astr.split()     如果len(strs)< 6:         strs.extend([b''] *(6-len(strs)))     返回b',' .join(strs)

使用字符串列表进行模拟(在Py3中):

In [139]: txt=b"""14        HO2       O3        OH        O2        O2
     ...: 15        HO2       HO2       H2O2      O2
     ...: 16        H2O2      OH        HO2       H2O
     ...: 17        O         O         O2
     ...: 18        O         O2        O3
     ...: 19        O         O3        O2        O2""".splitlines()

In [140]: [foo(l) for l in txt]
Out[140]: 
[b'14,HO2,O3,OH,O2,O2',
 b'15,HO2,HO2,H2O2,O2, ',
 b'16,H2O2,OH,HO2,H2O, ',
 b'17,O,O,O2, , ',
 b'18,O,O2,O3, , ',
 b'19,O,O3,O2,O2, ']

In [141]: np.genfromtxt([foo(l) for l in txt], dtype=None, delimiter=',')
Out[141]: 
array([(14, b'HO2', b'O3', b'OH', b'O2', b'O2'),
       (15, b'HO2', b'HO2', b'H2O2', b'O2', b''),
       (16, b'H2O2', b'OH', b'HO2', b'H2O', b''),
       (17, b'O', b'O', b'O2', b' ', b''),
       (18, b'O', b'O2', b'O3', b' ', b''),
       (19, b'O', b'O3', b'O2', b'O2', b'')], 
      dtype=[('f0', '<i4'), ('f1', 'S4'), ('f2', 'S3'), ('f3', 'S4'), ('f4', 'S3'), ('f5', 'S2')])

答案 1 :(得分:0)

看起来您的数据在10个字符的字段中很好地对齐。如果总是如此,您可以通过在genfromtxt参数中指定字段宽度序列来告诉delimiter要使用的字段宽度。

以下是一个例子。

首先,您的数据文件:

In [20]: !cat reaction.dat
14        HO2       O3        OH        O2        O2
15        HO2       HO2       H2O2      O2
16        H2O2      OH        HO2       H2O
17        O         O         O2
18        O         O2        O3
19        O         O3        O2        O2

为方便起见,我在这里定义字段数和字段宽度。 (通常,并非所有字段都必须具有相同的宽度。)

In [21]: numfields = 6

In [22]: fieldwidth = 10

通过传递参数genfromtxt告诉delimiter=(10, 10, 10, 10, 10, 10)数据是固定宽度列:

In [23]: data = genfromtxt('reaction.dat', dtype='S%d' % fieldwidth, delimiter=(fieldwidth,)*numfields)

这是结果。请注意&#34;缺少&#34;字段是空字符串。另请注意,非空字段包括空格,每行中的最后一个非空字段包含换行符:

In [24]: data
Out[24]: 
array([[b'14        ', b'HO2       ', b'O3        ', b'OH        ',
        b'O2        ', b'O2\n'],
       [b'15        ', b'HO2       ', b'HO2       ', b'H2O2      ',
        b'O2\n', b''],
       [b'16        ', b'H2O2      ', b'OH        ', b'HO2       ',
        b'H2O\n', b''],
       [b'17        ', b'O         ', b'O         ', b'O2\n', b'', b''],
       [b'18        ', b'O         ', b'O2        ', b'O3\n', b'', b''],
       [b'19        ', b'O         ', b'O3        ', b'O2        ',
        b'O2\n', b'']], 
      dtype='|S10')

In [25]: data[1]
Out[25]: 
array([b'15        ', b'HO2       ', b'HO2       ', b'H2O2      ', b'O2\n',
       b''], 
      dtype='|S10')

我们可以在第二步中清理字符串,或者我们可以genfromtxt通过为每个字段提供一个转换器来完成它,只需从字段中去除空白区域:

In [26]: data = genfromtxt('reaction.dat', dtype='S%d' % fieldwidth, delimiter=(fieldwidth,)*numfields, converters={k: lambda s: s.
    ...: strip() for k in range(numfields)})

In [27]: data
Out[27]: 
array([[b'14', b'HO2', b'O3', b'OH', b'O2', b'O2'],
       [b'15', b'HO2', b'HO2', b'H2O2', b'O2', b''],
       [b'16', b'H2O2', b'OH', b'HO2', b'H2O', b''],
       [b'17', b'O', b'O', b'O2', b'', b''],
       [b'18', b'O', b'O2', b'O3', b'', b''],
       [b'19', b'O', b'O3', b'O2', b'O2', b'']], 
      dtype='|S10')

In [28]: data[:,0]
Out[28]: 
array([b'14', b'15', b'16', b'17', b'18', b'19'], 
      dtype='|S10')

In [29]: data[:,5]
Out[29]: 
array([b'O2', b'', b'', b'', b'', b''], 
      dtype='|S10')