使用NumPy读取大型格式化文本文件

时间:2013-02-18 22:42:46

标签: numpy python-2.7

我自愿帮助某人将有限元网格从一种格式转换为另一种格式(i-deas * .unv to Alberta)。我已经使用NumPy对网格进行了一些额外的修改,但是我在将原始文本文件数据读入NumPy数组时遇到了问题。到目前为止,我已经尝试过genfromtxt和loadtxt但没有成功。

一些细节:

1)所有组都由页眉和页脚标志“-1”分隔。

2)NODE组在其自己的行上有一个标题“2411”。我只想读取该组中的替换行,用4个整数跳过每一行,但是用3个Fortran双精度数读取该行。

3)ELEMENT连接组在其自己的行上有一个标题“2412”。所有数据都是整数,只需要读取前4列。由于缺少2和3个节点元素的值,NumPy阵列中将有一些空插槽。

4)“2477”节点组我认为我可以使用正则表达式处理自己,找到要读取的行。

5)真正的数据文件将有大约100万行文本,所以我非常希望它尽可能地被矢量化(或者NumPy快速读取内容)。

很抱歉,如果我提供了太多信息,谢谢。

以下行是* .unv文本文件格式的部分示例。

    -1
  2411
  146303         1         1        11
  6.9849462399269246D-001  8.0008842847097805D-002  6.6360238055630028D-001
  146304         1         1        11
  4.1854795755893875D-001  9.1256034628308313D-001  3.5725496189239300D-002
  146305         1         1        11
  7.5541258490349616D-001  3.7870257739063029D-001  2.0504544370783115D-001
  146306         1         1        11
  2.7637569971086767D-001  9.2829777518336010D-001  1.3757239038663285D-001
   -1
   -1
 2412
     9        21         1         0         7         2
     0         0         0
     1         9
    10        21         1         0         7         2
     0         0         0
     9        10
  1550        91         6         0         7         3
   761      3685      2027
  1551        91         6         0         7         3
   761      2380      2067
 39720       111         1         0         7         4
 71854     59536     40323     73014
 39721       111         1         0         7         4
 45520     48908    133818    145014
   -1
   -1
   2477
     1         0         0         0         0         0         0      3022
PERMANENT GROUP1
     7         2         0         0         7         3         0         0
     7         8         0         0         7         7         0         0
     7       147         0         0         7       148         0         0
     2         0         0         0         0         0         0      2915
PERMANENT GROUP2
     7         1         0         0         7         5         0         0
     7         4         0         0         7         6         0         0
     7         9         0         0         7        11         0         0
   -1

1 个答案:

答案 0 :(得分:4)

numpy方法genfromtxtloadtxt很难应用于整个文件,因为您的数据具有非常特殊的结构(根据您所在的节点而变化)。因此,我建议采用以下策略:

  • 逐行读取文件,尝试通过分析该行确定您所在的节点。

  • 如果您所在的节点只有少量数据(例如,您必须读取交替的行,因此无法连续读取),请逐行读取并处理线。

  • 当您到达包含大量数据的部分(如带有“真实数据”的部分)时,请使用numpys fromfile方法读取数据,如下所示:

    mydata = np.fromfile(fp, sep=" ", dtype=int, count=number_of_elements)
    mydata.shape = (100000, 3)    # Reshape it to the desired shape as fromfile
                                  # returns a 1D array.
    

通过这种方式,您可以将逐行处理的灵活性与快速读取和转换大块数据的能力结合起来。

更新:关键是,你打开文件,逐行读取,当你到达一个有大量数据的地方时,你将文件描述符传递给fromfile。

以下简化示例:

import numpy as np

fp = open("test.dat", "r")
line = fp.readline()
ndata = int(line.strip())
data = np.fromfile(fp, count=ndata, sep=" ", dtype=int)
fp.close()

这将从文件test.dat中读取数据,内容如下:

10
1 2 3 4 5
6 7 8 9 10

第一行用fp.read()显式读取,处理(确定要读取的整数的数量),然后np.fromfile()读取相应的数据块并将其存储在1D数组中{ {1}}。

UPDATE2:或者,您可以将整个文本读入缓冲区,然后确定大块数据的起始位置和结束位置,并直接通过data进行转换:

np.fromstring

或者,如果很容易将其表达为一个正则表达式,则可以直接在文件上使用fp = open("test.dat", "r") txt = fp.read() fp.close() # Now determine starting and end positions (startpos, endpos) # .. # pass text that portion of the text to the fromstring function. data = np.fromstring(txt[startpos:endpos], dtype=int, sep=" ")