如何通过numpy读取文件时将不同长度的字符串(例如'-----'和' - ')替换为nans?

问题描述 投票:1回答:1

假设我有一个包含日期时间和一些相关数据的示例文本文件,如下所示。

1996/01/15  07:01:10    262     43    525     600    454      0    -31.1    -------    -------    272  
1996/01/22  03:11:01    105     37    267     401    130      0   -126.3*   7.1e+13*   2.5e+28*   103   
1996/01/26  09:16:19     90     27    262     254    271    322      1.9*   3.0e+14    1.0e+29     90   
1996/01/31  06:52:13    274     47    158     219     99      0    -12.3*   2.5e+14*   3.2e+28*   272   
1996/02/03  00:07:03     83     52    306     294    317    309      0.9*   1.9e+15    8.9e+29     80   
1996/02/08  05:17:49    263     70    184     247    126      0     -6.0*   1.6e+14    2.7e+28    249  
1996/02/12  05:47:26     91     53    160     100    211    236      2.0*   1.3e+15    1.6e+29     92  
1996/02/17  02:06:31    279     73    317     257    378    532      9.9*   3.3e+14*   1.6e+29*   274  
1996/02/17  05:18:59     86     36    171      64    279    819     27.9*   2.1e+14*   3.1e+28*    88   
1996/02/19  05:15:48     98     30    266     129    403    946     36.7*   1.3e+14*   4.6e+28*    94   
1996/03/02  04:11:53     88     36    108      95    120    177      1.0*   1.5e+14    8.7e+27     86  
1996/03/03  04:12:30     99     26    186     141    232    215      2.3*   1.6e+14*   2.8e+28*    99  
1996/03/06  05:38:36    268     55    175    ----   ----   ----   ------    3.6e+13*   5.6e+27*   261   

我希望能够识别非数值数据的行和列,例如上面显示的----。我originally used numpy to replace -的每个实例零,但这证明有问题,因为我可能想跳过该行而不是使用替换值。 According to this SO post,numpy可以正确读取NAN值。所以我接着用----替换了np.nan。最终结果是我的一个错误; -的数量对于每一行和每列都不相同。我想有一些类型的lambda解决方案来取代-的完整字符串,甚至可能是一个更简单的解决方案。

作为参考,您可以将以下内容放在文本文件中,并使用下面显示的代码进行阅读。

filename = "/Users/fpath" + "fname.txt"
ncols = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
nskip = 0
data = np.loadtxt(filename, skiprows=nskip, usecols=ncols, dtype=str) 
# dtype=str is used above since float(---) and int(---) will not work
# data = np.char.replace(data, '-', 'Z')
print(data)

编辑:一个微妙的复杂性也是第9列(索引= 8)包含一些负值。

string python-3.x file numpy nan
1个回答
1
投票

这是使用具有显式列宽的genfromtxt的相对无痛的方式。 genfromtxt取代了它无法用NaN解析的任何东西,所以不需要在不同长度的'---'字符串上出汗:

>>> widths
[4, 1, 2, 1, 2, 4, 1, 2, 1, 2, 7, 7, 7, 8, 7, 7, 9, 1, 10, 1, 10, 1, 6]
>>> types
[<class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, 'U2', <class 'float'>, 'U2', <class 'float'>, 'U2', <class 'float'>]
>>> np.genfromtxt(io.StringIO(data), delimiter=widths, usecols=np.r_[:5:2, 5:10:2, 10:23], dtype=types)array([(1996., 1., 15., 7.,  1., 10., 262., 43., 525., 600., 454.,   0.,  -31.1, ' ',     nan, ' ',     nan, ' ', 272.),
       (1996., 1., 22., 3., 11.,  1., 105., 37., 267., 401., 130.,   0., -126.3, '*', 7.1e+13, '*', 2.5e+28, '*', 103.),
       (1996., 1., 26., 9., 16., 19.,  90., 27., 262., 254., 271., 322.,    1.9, '*', 3.0e+14, ' ', 1.0e+29, ' ',  90.),
       (1996., 1., 31., 6., 52., 13., 274., 47., 158., 219.,  99.,   0.,  -12.3, '*', 2.5e+14, '*', 3.2e+28, '*', 272.),
       (1996., 2.,  3., 0.,  7.,  3.,  83., 52., 306., 294., 317., 309.,    0.9, '*', 1.9e+15, ' ', 8.9e+29, ' ',  80.),
       (1996., 2.,  8., 5., 17., 49., 263., 70., 184., 247., 126.,   0.,   -6. , '*', 1.6e+14, ' ', 2.7e+28, ' ', 249.),
       (1996., 2., 12., 5., 47., 26.,  91., 53., 160., 100., 211., 236.,    2. , '*', 1.3e+15, ' ', 1.6e+29, ' ',  92.),
       (1996., 2., 17., 2.,  6., 31., 279., 73., 317., 257., 378., 532.,    9.9, '*', 3.3e+14, '*', 1.6e+29, '*', 274.),
       (1996., 2., 17., 5., 18., 59.,  86., 36., 171.,  64., 279., 819.,   27.9, '*', 2.1e+14, '*', 3.1e+28, '*',  88.),
       (1996., 2., 19., 5., 15., 48.,  98., 30., 266., 129., 403., 946.,   36.7, '*', 1.3e+14, '*', 4.6e+28, '*',  94.),
       (1996., 3.,  2., 4., 11., 53.,  88., 36., 108.,  95., 120., 177.,    1. , '*', 1.5e+14, ' ', 8.7e+27, ' ',  86.),
       (1996., 3.,  3., 4., 12., 30.,  99., 26., 186., 141., 232., 215.,    2.3, '*', 1.6e+14, '*', 2.8e+28, '*',  99.),
       (1996., 3.,  6., 5., 38., 36., 268., 55., 175.,  nan,  nan,  nan,    nan, ' ', 3.6e+13, '*', 5.6e+27, '*', 261.)],
      dtype=[('f0', '<f8'), ('f2', '<f8'), ('f4', '<f8'), ('f5', '<f8'), ('f7', '<f8'), ('f9', '<f8'), ('f10', '<f8'), ('f11', '<f8'), ('f12', '<f8'), ('f13', '<f8'), ('f14', '<f8'), ('f15', '<f8'), ('f16', '<f8'), ('f17', '<U2'), ('f18', '<f8'), ('f19', '<U2'), ('f20', '<f8'), ('f21', '<U2'), ('f22', '<f8')])

选择星形列的dtype 'U2'来匹配浮点数的大小,因此我们可以轻松地查看和提取数值数据。

>>> mixed = np.genfromtxt(io.StringIO(data), delimiter=widths, usecols=np.r_[:5:2, 5:10:2, 10:23], dtype=types)
>>> numerical_data = mixed.view(float).reshape(-1, 19)[:, np.r_[:12, 12:19:2]]
© www.soinside.com 2019 - 2024. All rights reserved.