2013-02-18 156 views
6

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

一些细节:

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

的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数组data中。

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()

+0

谢谢你的建议。看一下“fromfile”命令,它看起来像从第一行读取文件,因此不会允许只读取特定块。我看着使用“open”命令为上面的“fp”定义了一个块,但是这似乎也只是从第一行读取文件。 – Tim 2013-02-19 12:00:28

+0

我在上面添加了一个简化的例子。 – 2013-02-19 12:13:54

+0

感谢您的拼写!我遗漏的一点是,readline()命令的作用是告诉fromfile命令它应该从当前行读取fp,而不是文件的开头。有没有办法将起始行设置为某个值,而无需多次调用readline()?我可以通过在一行的开始处搜索字符串“-1”来快速找到数据块开始和结束处的行号,但必须在循环中调用readline()才能达到所需的起始点有点缓慢的事情。谢谢! – Tim 2013-02-19 13:09:05