2009-08-10 52 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]