问题描述
||
我需要将ASCII文件读入Python,该文件的摘录如下所示:
E M S T N...
...
9998 1 1 128 10097 10098 10199 10198 20298 20299 20400 20399
9999 1 1 128 10098 10099 10200 10199 20299 20300 20401 20400
10000 1 1 128 10099 10100 10201 10200 20300 20301 20402 20401
10001 1 2 44 2071 2172 12373 12272
10002 1 2 44 2172 2273 12474 12373
理想情况下,以上内容应遵循NumPy模式:
array([(9998,1,128,(10097,10098,10199,10198,20298,20299,20400,20399)),(9999,(10098,10099,10200,20300,20401,20400)),(10000,(10099,10100,10201,20301,20402,20401)),(10001,2,44,(2071,2172,12373,12272)),(10002,(2172,2273,12474,12373))],dtype=[(\'E\',\'<i4\'),(\'M\',(\'S\',(\'T\',(\'N\',\'|O4\')])
最后一个对象N
是一个tuple
,其整数在2到8之间。
我想使用np.loadtxt
或np.genfromtxt
加载这个衣衫structure的结构,除了我不确定是否可以这样做。有内置的技巧,还是我需要自定义循环分割?
解决方法
据我所知,您确实需要一个自定义的\“ split-cast \\”用于循环。
实际上,NumPy可以读取像您一样的嵌套结构,但是它们必须具有固定的形状,例如
numpy.loadtxt(\'data.txt\',dtype=[ (\'time\',np.uint64),(\'pos\',[(\'x\',np.float),(\'y\',np.float)]) ])
当尝试使用所需的dtype读取数据时,NumPy仅读取每个元组的第一个数字:
dt=[(\'E\',\'<i4\'),(\'M\',(\'S\',(\'T\',(\'N\',\'|O4\')]
print numpy.loadtxt(\'data.txt\',dtype=dt)
因此打印
[(9998,1,128,\'10097\')
(9999,\'10098\')
(10000,\'10099\')…]
因此,我要说继续使用for循环而不是numpy.loadtxt()
。
您还可以使用一种可能更快的中间方法:让NumPy使用上面的代码加载文件,然后手动“校正” \'N \'字段:
dt=[(\'E\',\'|O4\')]
arr = numpy.loadtxt(\'data.txt\',dtype=dt) # Correctly reads the first 4 columns
with open(\'data.txt\') as input_file:
for (line_num,line) in enumerate(input_file):
arr[line_num][\'N\'] = tuple(int(x) for x in line.split()[4:]) # Manual setting of the tuple column
这种方法可能比在for循环中解析整个数组更快。这将产生您想要的结果:
[(9998,(10097,10098,10199,10198,20298,20299,20400,20399))
(9999,(10098,10099,10200,20300,20401,20400))
(10000,(10099,10100,10201,20301,20402,20401))
(10001,2,44,(2071,2172,12373,12272))
(10002,(2172,2273,12474,1237))]