【问题标题】:Save data from separate columns in a file into a variable in Python 2.7将文件中不同列中的数据保存到 Python 2.7 中的变量中
【发布时间】:2013-06-09 09:31:01
【问题描述】:

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

  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

现在我想读取第 1 列并将其保存到列表 'u' 中,将第 2 列保存到列表 '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 中执行此操作的任何想法? (我必须以迭代的方式对非常大数据集执行此操作,因此快速高效的代码将大有裨益)

【问题讨论】:

  • 我不明白你如何处理数据标题行?
  • 我没有在代码中提到它,但是我可以跳过第一行被阅读。我把那个标题让其他人理解我的数据意味着什么。对不起,如果这让你感到困惑..
  • 你的数据集有多大?
  • 我会有 7 - 8 列,每列至少有 8000 - 10000 个数字。我必须在我正在运行的数值模拟代码的每次迭代中执行此操作。
  • 要将各种实现与您的真实数据集进行比较,您可以使用timeit。如果你分享你的结果会很酷!

标签: python file-io python-2.7


【解决方案1】:

请更改内循环:

   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():”中的语句将被执行四次(对于每一列)。

【讨论】:

    【解决方案2】:

    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: How much space does each element of a list take?),这给了我不到 1MB 的内存来一次保存所有数据。就内存消耗而言,这是非常小的数据集。

    【讨论】:

    • +1。我将尝试这些方法中的每一种,并让大家了解它们在性能方面的表现。
    【解决方案3】:

    如果我理解得很好,通过使用 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]
    

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

    编辑:zip 替换为 izip 以在 python 2.x 上使用生成器

    【讨论】:

    • 如果在加载整个数据文件时数据集很大 (YMMV),这将不适合内存。
    • @yaccz 我不确定你的说法。我的理解是内部结构是一个生成器,因此会在 zip 请求它们时逐行读取,使用后丢弃以前的输入数据行。我不知道“明星运营商”* 将如何影响这种预期行为。如果使用 izip 而不是 zip 对该域有任何影响,也不会产生任何影响。除此之外,我认为这与您 40 分钟前在编辑中提出的解决方案完全相同。
    • 我认为这取决于python版本。当我查看手册时,py3.2 zip() 似乎正在返回生成器,但是 py2.7 返回一个列表,整个文件将被加载到内存中,iiuc。
    • @yaccz 我已经相应地改变了答案。我不确定这对内存占用有巨大影响,因为 u,v,w,p = izip(...) 语句(这是否针对生成器进行了优化?)也许使用 itertools.islice 提取列可能会导致更好的解决方案?
    • 1.这与它的优化无关,而与它的返回值有关。 2. 我怀疑 islice 会提高性能,我当然不会认为它很优雅。 3. 也和论据展开没有任何关系。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多