Numpy,从文件读取没有分隔符但是固定模式

时间:2014-12-16 14:34:59

标签: python numpy genfromtxt

我尝试搜索这个问题,但我找不到那些看似不太复杂的答案。

我正在从只有空格分隔符的文件中读取。列不是固定宽度。前两列是给我这个问题的。它是15列,前两个是字符串,其他一切都是浮点数。

我尝试使用numpy" genfromtxt"并指定了dtype。但是,某些字符串条目为空或包含数字,因此这些行被误读为具有15或17个条目。

以下是几行线的示例。

NGC 104    47 Tuc       00 24 05.67  -72 04 52.6   305.89  -44.89    4.5   7.4   1.9  -2.6  -3.1
NGC 288                 00 52 45.24  -26 34 57.4   152.30  -89.38    8.9  12.0  -0.1   0.0  -8.9
NGC 362                 01 03 14.26  -70 50 55.6   301.53  -46.25    8.6   9.4   3.1  -5.1  -6.2
Whiting 1               02 02 57     -03 15 10     161.22  -60.76   30.1  34.5 -13.9   4.7 -26.3

我该如何处理?我应该重新格式化文本,然后将其输出为CSV格式吗?我应该读作正则表达式吗?我可以修复此命令:

data = np.genfromtxt('PositionalData.txt', skiprows=0, missing_values=(' '), dtype=['S6','S6', 'f4', 'f4', 'f4', 'f4', 'f4', 'f4', 'f5','f4','f4', 'f4', 'f4', 'f4', 'f4'])

谢谢,非常感谢帮助。

编辑:

使用一些固定宽度设置后,这是一些输出:

(' NG', 'C 1', 0.0, 4.0, nan, nan, nan, nan, 4.0, 7.0, nan, nan, nan, nan, nan)
(' NG', 'C 2', 8.0, 8.0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan)
(' NG', 'C 3', 6.0, 2.0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan)
(' Wh', 'iti', nan, nan, nan, 1.0, nan, nan, nan, nan, nan, nan, nan, nan, nan)
(' NG', 'C 1', 2.0, 6.0, 1.0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan)
(' Pa', 'l 1', nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan)

命令为data = np.genfromtxt('PositionalDataTest.txt', skiprows=0,delimiter=(3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), missing_values=(' '), dtype=['S7','S7', 'f4', 'f4', 'f4', 'f4', 'f4', 'f4', 'f5','f4','f4', 'f4', 'f4', 'f4', 'f4'])

这些行是:

NGC 104    47 Tuc       00 24 05.67  -72 04 52.6   305.89  -44.89    4.5   7.4   1.9  -2.6  -3.1
NGC 288                 00 52 45.24  -26 34 57.4   152.30  -89.38    8.9  12.0  -0.1   0.0  -8.9
NGC 362                 01 03 14.26  -70 50 55.6   301.53  -46.25    8.6   9.4   3.1  -5.1  -6.2
Whiting 1               02 02 57     -03 15 10     161.22  -60.76   30.1  34.5 -13.9   4.7 -26.3
NGC 1261                03 12 16.21  -55 12 58.4   270.54  -52.12   16.3  18.1   0.1 -10.0 -12.9
Pal 1                   03 33 20.04  79 34 51.8   130.06   19.03   11.1  17.2  -6.8   8.1   3.6

1 个答案:

答案 0 :(得分:2)

考虑数据文件的这一部分:

-72 04 52.6 
-26 34 57.4 
-70 50 55.6 
-03 15 10   
-55 12 58.4 
79 34 51.8  

可以这样解析:

In [75]: np.genfromtxt('data2', delimiter=[3,3,5], dtype=None).tolist()
Out[75]: 
[(-72, 4, 52.6),
 (-26, 34, 57.4),
 (-70, 50, 55.6),
 (-3, 15, 10.0),
 (-55, 12, 58.4),
 (79, 34, 51.8)]

可以类似地解析文件的其余部分,难点在于找到要在delimiter中使用的正确列宽。

这很费力,我宁愿不这样做,因为这个解决方案很脆弱。 使用固定宽度的列很可能无法解析您的数据。

因此,让我们拍摄一个强大的解决方案。 np.genfromtxt可以接受任何可迭代的字符串作为其第一个参数。 因此,我们可以通过简单地定义生成器函数来预处理文件中的行,从而充分利用Python字符串操作来解决问题。 我们为所有这些功能付出的代价是,每行调用一次Python函数将比使用简单分隔符或固定宽度列解析文件时使用的C代码np.genfromtxt慢得多。

import numpy as np
def process(iterable):
    for line in iterable:
        parts = [line[:11], line[11:24]] + line[24:].split()
        yield '@'.join(parts)
with open('data', 'rb') as f:
    data = np.genfromtxt(process(f), dtype=None, delimiter='@')

print(repr(data))

产量

array([ ('NGC 104    ', '47 Tuc       ', 0, 24, 5.67, -72, 4, 52.6, 305.89, -44.89, 4.5, 7.4, 1.9, -2.6, -3.1),
       ('NGC 288    ', '             ', 0, 52, 45.24, -26, 34, 57.4, 152.3, -89.38, 8.9, 12.0, -0.1, 0.0, -8.9),
       ('NGC 362    ', '             ', 1, 3, 14.26, -70, 50, 55.6, 301.53, -46.25, 8.6, 9.4, 3.1, -5.1, -6.2),
       ('Whiting 1  ', '             ', 2, 2, 57.0, -3, 15, 10.0, 161.22, -60.76, 30.1, 34.5, -13.9, 4.7, -26.3),
       ('NGC 1261   ', '             ', 3, 12, 16.21, -55, 12, 58.4, 270.54, -52.12, 16.3, 18.1, 0.1, -10.0, -12.9),
       ('Pal 1      ', '             ', 3, 33, 20.04, 79, 34, 51.8, 130.06, 19.03, 11.1, 17.2, -6.8, 8.1, 3.6)], 
      dtype=[('f0', 'S11'), ('f1', 'S13'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<f8'), ('f5', '<i8'), ('f6', '<i8'), ('f7', '<f8'), ('f8', '<f8'), ('f9', '<f8'), ('f10', '<f8'), ('f11', '<f8'), ('f12', '<f8'), ('f13', '<f8'), ('f14', '<f8')])

请注意,process函数使用'@'作为列之间的分隔符。如果数据包含'@',则必须为分隔符选择其他字符。