2009-08-10 181 views
3

我是新來的python,我有一個問題。 我有一些測量數據保存在一個txt文件中。 數據與製表符分隔,它具有這樣的結構:從一個txt文件創建一個數組

0 0 -11.007001 -14.222319 2.336769 

我有每模擬總是32個數據點(0,1,2,...,31)和i具有300個模擬(0,1, 2 ...,299),所以數據首先按照模擬的數量和數據點的數量進行排序。

第一列是模擬編號,第二列是數據點編號,其他3列是x,y,z座標。

我想創建一個3d數組,第一維應該是模擬編號,第二個數據點的編號和第三個三個座標。

我已經開始了一下,這裏是我到目前爲止有:

## read file 
coords = [x.split('\t') for x in 
      open(f,'r').read().replace('\r','')[:-1].split('\n')] 
## extract the information you want 
simnum = [int(x[0]) for x in coords] 
npts = [int(x[1]) for x in coords] 
xyz = array([map(float,x[2:]) for x in coords]) 

,但我不知道如何將這些2只列出了這一個陣列相結合。

到底我想有這樣的事情:

陣列= [simnum] [num_dat_point] [XYZ]

感謝您的幫助。

我希望你能理解我的問題,這是我第一次在python論壇發帖,所以如果我做錯了什麼,我對此感到抱歉。

再次感謝

+3

這不只是一個Python論壇上,我增加了蟒蛇標記,以便正確的人更容易看到你的問題,並改變了頂部的格式,因此總結對於查看所有問題列表的人來說更具信息性 – 2009-08-10 17:24:40

回答

2

你可以用zip function將它們組合起來,就像這樣:

for sim, datapoint, x, y, z in zip(simnum, npts, *xyz): 
    # do your thing 

,或者你可以完全避免列表理解,只是遍歷文件的行:

for line in open(fname): 
    lst = line.split('\t') 
    sim, datapoint = int(lst[0]), int(lst[1]) 
    x, y, z = [float(i) for i in lst[2:]] 
    # do your thing 

解析一個單行,你可以(並應該)做到以下幾點:

coords = [x.split('\t') for x in open(fname)] 
+0

你說你的迭代示例「[完全避免]列表解析」,但是你可以在第二步中使用一個,最後一行。 – JAB 2009-08-10 17:45:52

+0

,你看不出我使用lc和OPs有什麼區別? – SilentGhost 2009-08-10 18:08:37

+0

@Cat:'map(float,lst [2:])'會做。 – 2009-08-10 18:13:41

2

根據python的禪意,flat比嵌套更好。我只是使用字典。

import csv 
f = csv.reader(open('thefile.csv'), delimiter='\t', 
       quoting=csv.QUOTE_NONNUMERIC) 

result = {} 
for simn, dpoint, c1, c2, c3 in f: 
    result[simn, dpoint] = c1, c2, c3 

# pretty-prints the result: 
from pprint import pprint 
pprint(result) 
+0

您忘記將數據轉換爲int或浮點數。 – 2009-08-10 22:55:37

+0

@John Machin:固定 – nosklo 2009-08-10 23:59:12

+0

不固定;可怕的QUOTE_NONNUMERIC噱頭將** ALL ** OP的數據隱式轉換爲浮點數。 – 2009-08-11 00:46:30

2

這似乎是一個使用itertools.groupby的好機會。

import itertools 
import csv 
file = open("data.txt") 
reader = csv.reader(file, delimiter='\t') 
result = [] 
for simnumberStr, rows in itertools.groupby(reader, key=lambda t: t[0]): 
    simData = [] 
    for row in rows: 
     simData.append([float(v) for v in row[2:]]) 
    result.append(simData) 
file.close() 

這將創建一個名爲'result'的3維列表。第一個索引是模擬編號,第二個索引是模擬中的數據索引。該值是包含x,y和z座標的整數列表。

請注意,這裏假定數據已經按照模擬編號和數據編號排序。

+0

greg - 你使用的python版本是什麼版本,csv.reader函數需要一個delimeter的爭論?我的Python 2.6不這樣做,它是在python 3中添加的嗎? – Petriborg 2009-08-10 18:07:40

+0

Petriborg - 我正在使用版本Python 2.5.2。它也記錄在這裏:http://docs.python.org/library/csv.html – Greg 2009-08-10 18:18:51

+1

@Petriborg,@Greg:如果您正確拼寫分隔符,它會更好。 – jcdyer 2009-08-10 19:08:12

1

基本上難點是如果不同的模擬具有不同數量的點會發生什麼。

您將因此需要第一尺寸數組添加到適當的大小。 t應該是一個至少爲max(simnum) x max(npts) x 3的數組。 爲避免混淆,你應該不是一個數初始化, 這將讓你看到失分。

然後使用類似

for x in coords: 
    t[int(x[0])][int(x[1])][0]=float(x[3]) 
    t[int(x[0])][int(x[1])][1]=float(x[4]) 
    t[int(x[0])][int(x[1])][2]=float(x[5]) 

這是你的意思?

+0

每個模擬具有完全相同的點數。 – steffen 2009-08-10 18:07:37

+0

好的。然後這段代碼應該可以正常工作,例如,t = [[[0,0,0]我在範圍(32)]中,j在範圍內(300)] – 2009-08-11 14:23:00

0

首先我想指出的是您的第一個數據點似乎是一個指標,並想知道如果數據是非常重要與否,而是取其:-)

def parse(line): 
    mch = re.compile('^(\d+)\s+(\d+)\s+([-\d\.]+)\s+([-\d\.]+)\s+([-\d\.]+)$') 
    m = mch.match(line) 
    if m: 
     l = m.groups() 
     (idx,data,xyz) = (int(l[0]),int(l[1]), map(float, l[2:])) 
     return (idx, data, xyz) 
    return None 

finaldata = [] 
file = open("data.txt",'r') 
for line in file: 
    r = parse(line) 
    if r is not None: 
     finaldata.append(r) 

最終數據應該沿着具有輸出的線路:

[(0, 0, [-11.007001000000001, -14.222319000000001, 2.3367689999999999]), 
(1, 0, [-11.007001000000001, -14.222319000000001, 2.3367689999999999]), 
(2, 0, [-11.007001000000001, -14.222319000000001, 2.3367689999999999]), 
(3, 0, [-11.007001000000001, -14.222319000000001, 2.3367689999999999]), 
(4, 0, [-11.007001000000001, -14.222319000000001, 2.3367689999999999])] 

這應該是相當強勁關於處理瓦特/空白問題(諸如此類的標籤空格)......

我也想知道你的數據文件有多大,我的通常很大,所以能夠以塊或組的方式處理它們......無論如何,這將在python 2.6中起作用。

1

您可以使用許多不同類型的容器爲你的目的,但他們都沒有array爲不合格的名稱 - Python有一個模塊array,您可以從標準庫中導入,但array.array類型太有限爲你的目的(只有一維和基本類型的內容);有一個流行的第三方擴展名爲numpy,它的確有一個強大的numpy.array類型,如果你已經下載並安裝了擴展,你可以使用它 - 但你從來沒有提過numpy我懷疑這就是你的意思;相關內建類型爲listdict。我假設你想要的任何容器,任何 - 但如果你能學會在將來使用精確的術語,這將大大幫助你和誰的人想幫你(說列表,當你的意思是列表,數組只有當你這樣做的意思數組,「容器」,當你不確定要使用什麼容器時,等等)。

我建議你看看csv模塊中的標準庫一個更強大的方式來閱讀你的數據,但是這是一個單獨的問題。讓我們從每個包含5個字符串的列表列表開始,每個子列表包含表示兩個整數後跟三個浮點數的字符串。另外兩個關鍵方面需要指定...

一個關鍵方面你不告訴我們:是列表中的一些顯著的方式排序?有沒有,特別是,你想保留一些重要的秩序?由於你甚至沒有提到這兩個問題,我將不得不採取這種或那種方式,我會假設沒有任何保證也沒有有意義的順序;但是,不重複(每對模擬/數據點數不允許出現一次以上)。

第二個關鍵方面:每個模擬的數據點數是否增加(0,1,2,...),或者不一定是這種情況(並且順便提一句,模擬本身編號爲0 ,1,2,...)?同樣,沒有從您的線索的規格上的這一不可或缺的組成部分 - 注意,你這是在強迫多少假設想成爲助手的只是不告訴我們對這種明顯的關鍵環節進行。不要讓那些想要幫助你的人在黑暗中跌倒:相反,學會ask questions the smart way - 這會爲你自己節省大量的時間,並且會幫助你,爲你提供更高質量和更相關的幫助,所以,爲什麼不做呢?無論如何,我們不得不做出另一個假設,我不得不假設什麼都不知道模擬數字,也不知道每個模擬中數據點的數量。

有了這些假設dict作爲外部容器使用的唯一合理的結構:一個字典,其關鍵是一個包含兩個項目的元組,模擬編號,然後是模擬中的數據點編號。這些值也可以是元組(每個都有三個浮點數),因爲它確實顯示每行只有3個座標。

所有這些假設...:

def make_container(coords): 
    result = dict() 
    for s, d, x, y, z in coords: 
    key = int(s), int(d) 
    value = float(x), float(y), float(z) 
    result[key] = value 
    return result 

它總是最好的,最快的,有內def語句(即作爲函數被調用,可能與適當的參數),因此所有顯著代碼我以這種方式呈現它。 make_container返回一個你可以用模擬號碼和數據點號碼解決的字典;例如,

d = make_container(coords) 
print d[0, 0] 

將打印的X,Y,Z爲SIM 0的DP 0,假設一個存在(如果這樣的SIM/DP組合不存在,你會得到一個錯誤)。字典有許多有用的方法,例如改變上面的print語句來

print d.get((0, 0)) 

(是的,你做需要雙括號在這裏 - 內部的人做一個元組,外部的調用get與元組作爲它的唯一參數),你會如果沒有像(0,0)那樣的sim/dp組合,請參閱None,而不是獲得例外。

如果您可以編輯您的問題以使您的規格更加精確(可能包括您計劃使用最終容器的方式以及上面列出的各種關鍵方面),我可能會根據你的需要和情況調整這個建議要好得多(以及其他響應者,關於他們自己的建議!),所以我強烈建議你這樣做 - 先謝謝你幫助我們幫助你! - )

+0

我指定了我的帖子。 我一直有32個數據點每個模擬(0,1,2,...,31),我有300個模擬(0,1,2 ...,299),所以數據首先按數字排序然後模擬數據點的數量。 我希望幫助和感謝的幫助,這是一個非常好的幫助。 對不起我的不公開發布方式,但我會盡力使它在未來更好。 再次感謝 – steffen 2009-08-10 19:24:57

+0

NP,我看到你已經接受了一個答案,所以這必定意味着答案已經解決了你的問題,所以我爲你感到高興! – 2009-08-10 21:23:43

0

你確定3D陣列是你想要的嗎?看起來你更想要一個二維數組,其中模擬編號是一維,數據點是第二個,然後存儲在該位置的值是座標。

此代碼會給你。

data = [] 
for coord in coords: 
    if coord[0] not in data: 
     data[coord[0]] = [] 
    data[coord[0]][coord[1]] = (coord[2], coord[3], coord[4]) 

爲了獲取座標在模擬7,數據點13,只是做數據[7] [13]