0

所以我在一个文件中有一个样本数据,它的安排是:

  u   v   w   p
 100 200 300 400 
 101 201 301 401
 102 202 302 402
 103 203 303 403 
 104 204 304 404
 105 205 305 405
 106 206 306 406
 107 207 307 407

现在我想读取第一列并将其保存到列表“u”中,将第二列保存到列表“v”中,以此类推,直到“p”为止。这是我到目前为止所拥有的:

import numpy as np
u  = []
v  = []
w  = []
p  = []

with open('testdata.dat') as f:
   for line in f:
       for x in line.split():
           u.append([int(x)])
           v.append([int(x)+1])
           w.append([int(x)+2])
           p.append([int(x)+3]) 

print 'u is'
print(u)
print 'v is'
print(v)
print 'w is'
print(w)
print 'p is'
print(p)

我尝试过改变索引,但显然这是错误的,因为我得到了输出

u is
[[100], [200], [300], [400], [101], [201], [301], [401], [102], [202], [302], 
 [402], [103], [203], [303], [403], [104], [204], [304], [404], [105], [205], 
 [305], [405], [106], [206], [306], [406], [107], [207], [307], [407]]

v is
[[101], [201], [301], [401], [102], [202], [302], [402], [103], [203], [303], 
 [403], [104], [204], [304], [404], [105], [205], [305], [405], [106], [206], 
 [306], [406], [107], [207], [307], [407], [108], [208], [308], [408]]

w is
[[102], [202], [302], [402], [103], [203], [303], [403], [104], [204], [304], 
 [404], [105], [205], [305], [405], [106], [206], [306], [406], [107], [207], 
 [307], [407], [108], [208], [308], [408], [109], [209], [309], [409]]

p is
[[103], [203], [303], [403], [104], [204], [304], [404], [105], [205], [305], 
 [405], [106], [206], [306], [406], [107], [207], [307], [407], [108], [208], 
 [308], [408], [109], [209], [309], [409], [110], [210], [310], [410]]

它只是通过索引增加行号并读取整行,而我希望将每一列的数据写入一个单独的变量,即对应于示例数据中给出的名称 - u = 100 --> 107, v = 200 --> 207 等

关于如何在 Python 中执行此操作的任何想法?(我必须以迭代的方式对非常大的数据集执行此操作,因此快速高效的代码将大有裨益)

4

3 回答 3

2

请更改内循环:

   for x in line.split():
       u.append([int(x)])
       v.append([int(x)+1])
       w.append([int(x)+2])
       p.append([int(x)+3]) 

   x = line.split()
   u.append([int(x[0])])
   v.append([int(x[1])])
   w.append([int(x[2])])
   p.append([int(x[3])])

在您的原始实现中,循环“for x in line.split():”中的语句将被执行四次(对于每一列)。

于 2013-06-09T09:37:35.407 回答
1

x.append([int(y)+c])附加一个元素的列表 -int(y)+c

您需要x.append(int(y)+c)获取数字列表而不是单例列表

这里也是相当不错的解决方案

from itertools import izip

a="""1 2 3 4
10 20 30 40"""

lines= ([int(y) for y in x.split()] for x in a.split("\n"))
cols = izip(*lines)

print list(cols)

印刷

[(1, 10), (2, 20), (3, 30), (4, 40)]

a.split("\n")在你的情况下会是open("data").readlines()左右

这应该会给您更好的内存性能,因为您将需要在任何给定时间内仅加载一行数据文件,除非您要继续计算并将生成器转换为列表。

但是,我不知道它在 CPU 方面的性能如何,但我的猜测是它可能会更好一些或与您的原始代码大致相同。

如果您要对此进行基准测试,那么仅使用列表而不是生成器并在 pypy 上尝试它也会很有趣(因为https://bitbucket.org/pypy/pypy/wiki/JitFriendliness看到生成器标题)如果你能适应它进入记忆。

考虑您的数据集

  (10**4 * 8 * 12)/1024.0

假设您的数字相对较小并且每个占用 12 个字节(Python:列表的每个元素占用多少空间?),这给了我不到 1MB 的内存来一次保存所有数据。就内存消耗而言,这是非常小的数据集。

于 2013-06-09T09:37:28.067 回答
1

如果我理解得很好,通过使用 Python 内置函数zipmap,您只需要一行即可:

from itertools import izip

u,v,w,p = izip(*(map(int,line.split()) for line in open('data.txt')))

# Usage (Python3 syntax)
print("u is", list(u))
print("v is", list(v))
print("w is", list(w))
print("p is", list(p))

产生以下结果:

u is [100, 101, 102, 103, 104, 105, 106, 107]
v is [200, 201, 202, 203, 204, 205, 206, 207]
w is [300, 301, 302, 303, 304, 305, 306, 307]
p is [400, 401, 402, 403, 404, 405, 406, 407]

由于这是您关心的问题,因此使用隐式循环zip并且map应该表现出比在 python 中执行它更好的性能(即使循环非常快)。我不确定这个解决方案是否有更好的内存占用思想......

编辑:替换zipizip即使在 python 2.x 上也可以使用生成器

于 2013-06-09T10:03:34.410 回答