6

我自愿帮助某人将有限元网格从一种格式转换为另一种格式(i-deas *.unv 到 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
4

1 回答 1

5

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-arraydata中。

UPDATE2:或者,您可以将整个文本读入缓冲区,然后确定大块数据的开始和结束位置并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=" ")

或者,如果很容易将其表述为一个正则表达式,则可以fromregex()直接在文件上使用。

于 2013-02-19T09:04:18.613 回答