从txt文件创建一个数组

时间:2009-08-10 17:19:12

标签: python arrays text

我是python的新手,我遇到了问题。 我有一些测量数据保存在txt文件中。 数据用制表符分隔,它具有以下结构:

0   0   -11.007001  -14.222319  2.336769

我每次模拟总共有32个数据点(0,1,2,...,31),我有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])

但我不知道如何将这两个列表和这一个数组合并。

最后我希望有这样的东西:

array = [simnum] [num_dat_point] [xyz]

感谢您的帮助。

我希望你理解我的问题,这是我在python论坛上发表的第一篇文章,所以如果我做错了什么,我很抱歉。

再次感谢

7 个答案:

答案 0 :(得分: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)]

答案 1 :(得分:2)

根据python的禅宗,flat比嵌套更好。我只是用dict。

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)

答案 2 :(得分: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坐标的整数列表。

请注意,这假设数据已经按模拟编号和数据编号排序。

答案 3 :(得分: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])

这是你的意思吗?

答案 4 :(得分:1)

您可以使用许多不同类型的容器,但没有一个具有array作为非限定名称 - Python有一个模块array,您可以从标准库导入,但是array.array类型对于您的目的来说太有限了(仅限1-D,基本类型作为内容);有一个流行的第三方扩展名为numpy,它有一个强大的numpy.array类型,如果你下载并安装了扩展程序,你可以使用它 - 但是你甚至从未提及过numpy 1}}我怀疑这就是你的意思;相关的内置类型为listdict。我假设你想要任何容器 - 但是如果你将来可以学会使用精确的术语,那将极大地帮助你和任何想要帮助你的人(比如列表,当你的意思是列表时,数组只有当你的意思是数组,“容器”,当你不确定要使用什么容器时,等等。)

我建议您查看标准库中的csv模块,以获得更健壮的数据读取方式,但这是一个单独的问题。让我们从拥有coords列表的列表开始,每个列表包含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]

将为sim 0的dp 0打印x,y,z,假设存在一个(如果不存在这样的sim / dp组合,则会出现错误)。 dicts有许多有用的方法,例如将上面的print语句更改为

print d.get((0, 0))

(是的,你在这里需要双括号 - 内部用于制作元组,外部用于将{t 1}作为单个参数调用get),你会看到如果没有(0,0)这样的sim / dp组合,则None,而不是异常。

如果您可以编辑您的问题以使您的规格更精确(可能包括您计划使用生成的容器的方式的一些指示,以及我上面列出的各个关键方面),我可能能够微调这个建议,以更好地满足您的需求和情况(也可能是其他响应者,关于他们自己的建议!),所以我强烈建议您这样做 - 提前感谢帮助我们! - )

答案 5 :(得分: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中运行。

答案 6 :(得分: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]