2013-02-18 48 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