将tabdelimited文件的列读入变量

时间:2013-05-08 00:52:11

标签: python tab-delimited

给定以下格式的制表符分隔文件,我需要以逐列方式执行操作。我知道的最简单的解决方案是使用pandas包,但是我的文件是几个演出,我很难阅读它。所以我决定使用普通的流媒体方法。

在这里,我想动态生成列变量(列数为~500),每个变量都将存储该特定列中的所有值,包括空白。例如: 变量a将是一个列表[11,22,31,,42,555]

a   b   c   d   e   f
11      9   9   1   6
22  8   0   8   2   
31  7       7   3   5
    6   1   6       4
42  6   2   5   2   3
555     3   4   1   2

如何通过只读一次整个文件来生成这些变量?

6 个答案:

答案 0 :(得分:2)

你真的有两个问题在这里。


  

我知道的最简单的解决方案是使用pandas包,但是我的文件是几个演出,我很难阅读它。所以我决定使用普通的流媒体方法。

不要那样做。与纯Python中编写的任何内容相比,Pandas可以处理大量数据,而且内存和时间要少得多。而且不那么冗长。可以想象,下降到numpy然后在阅读后将结果分析将有所帮助,但是保证降低到纯Python会使事情变得更糟。

如果您的代码有问题,请向我们展示您的代码(以及生成等效示例数据的足够信息)。


  

在这里,我想动态生成列变量(列数为~500),每个变量都将存储该特定列中的所有值,包括bank。例如:变量a将是一个列表[11,22,31,,42,555]。

绝对不要这样做。你几乎不想像这样动态生成变量。它没有任何好处,并且有很多缺点。

这正是词典的用途。而不是:

for column in columns:
    create_variable_named(column[0]).set_to(column[1:])

这样做:

column_dict = {column[0]: column[1:] for column in columns}

然后你可以像这样访问它:

column_dict['a']

并且,如果您想迭代所有列,而不是:

for col in a, b, c, d, …, zz, aaa, …:

你可以这样做:

for col in column_dict.values():

如果你真的,真的想创建动态变量,你可以。根据您要将其添加到的范围或命名空间,它是以下之一:

globals()[name] = value
locals()[name] = value
setattr(module, name, value)
setattr(obj, name, value)
setattr(cls, name, value)

......等等。

答案 1 :(得分:1)

如果你真的不想使用pandas,最好使用numpy,因为numpy确实有转置效果,所以你可以改变它以使列成为索引!

import csv
import numpy as np
with open('file_name.csv', 'rb') as f:
    reading = csv.reader(f,delimiter='\t')
    columns = reading.next()
    hold_files = []
    for row in reading:
        hold_files.append(row)
    data = np.array(hold_files)
    data = data.T

现在data是一个数组,其中每个项目都是一个数组,其中包含每列中的每个项目!仍然昂贵的熊猫仍然更好,但这确实回答了你的问题!

另外,我建议使用pickle将其保存到磁盘!这将花费更多的时间,但你不必再次迭代它!以下是您将如何做到这一点:

import pickle
def pickleSave(data, pickleFile):
    output = open(pickleFile, 'wb')
    pickle.dump(data, output)
    output.close()
    print "file has been saved to %s" % (pickleFile)
def pickleLoad(pickleFile):
    pkl_file = open(pickleFile, 'rb')
    data = pickle.load(pkl_file)
    pkl_file.close()
    return data

这会将data中的任何内容,数组,数据框等保存到您想要的任何文件名中:pickleFile

以下将保存我刚刚制作的数组!

file_name = "my_array.txt"
pickleSave(data,file_name)

现在,只要您想使用该数组,就可以保存它并使用以下内容加载它:

loaded_data = pickleLoad("my_array.txt")

现在变量loaded_data包含我之前创建的数组!您可以在任何类型的文件上使用它!

答案 2 :(得分:1)

来自评论:

  

它无法将整个文件加载到内存中,看起来像是永远加载。

如果这是你的问题,那你的攻击是错误的。如果你没有足够的内存来同时保存整个文件,你可能没有足够的时间来保持整个数组。如果您使用的是纯Python对象,那么肯定是,但可能不会使用pandasnumpy

因此,您需要做的是将其从一种基于磁盘的格式转换为另一种格式,然后重写代码以便比原始文件更快地处理磁盘上的数据。

一个明显的可能性是您可以随机访问搜索或mmap的文件。例如,假设您有500列完全符合range(0, 1<<32)的值,并且您不知道有多少行。

迭代csv只计算行数,然后创建4 * 500 * rows字节的文件,然后再次迭代csv以使用struct模块填充它。然后,您只需在mmap上创建4 * rows * col, 4 * rows * (col+1)视图即可访问任意列。

或者,或者,即时转置。这将更简单,并且具有一半的I / O,但可能更慢(因为内存和磁盘缓存效应)。

如果您只需要按列随机访问,而不是按行,只需为每列创建一个文件,并处理任何列,只需mmap相应的文件,或通过{{1}阅读它}或struct,或者只使用arraypandas来读取/写入每个(或可能只是numpy pickle表/ pandas数组直接)。

另一种可能性是使用键值数据库并在其中存储大blob,相当于文件。 (事实上​​,如果您计划使用pickle tables / arrays,numpy是一个键值数据库,其值通过pickle持久化。)

要从这些想法中随意挑选,下面是您如何创建单独的文件,动态转置以及使用shelve.shelf存储数据:

让我举一个单独文件和struct

的示例
struct

现在,要稍后访问一个列:

import csv
import struct

# You may want to check whether the column_foo.dat files already exist and are
# at least as new as input.csv, so you don't re-generate them unless the input
# data changes. That's obviously only a worthwhile optimization if you run the
# script multiple times on the exact same input.

with open('input.csv', 'rb') as f:
    reader = csv.reader(f, delimiter='\t'):
    column_names = next(reader)
    column_files = [open('column_{}.dat'.format(column_name), 'wb')
                    for column_name in column_names]
    for row in reader:
        for i, col in enumerate(row):
            value = int(col)
            column_files[i].write(struct.pack('!I', value))
    for f in column_files:
        f.close()

答案 3 :(得分:0)

尝试列表字典:

with open('myfile.txt', 'r') as infile:
    header = infile.readline()
    col_values = {var:[] for var in header.split()}
    var_idx_dict = {idx:var for idx,var in enumerate(header.split())}

    for line in infile:
        values = line.split('\t')

        for idx,value in enumerate(values):
            var = var_idx_dict[idx]
            col_values [var].append(value)

col_values应包含列标题的字符串键,每个键都指向该列中所有值的列表。

编辑:鉴于您的文件非常大且我不了解您的环境,并且您在使用pandas时遇到问题,请考虑尝试使用PyTables。我可以提供一些帮助...这取决于你的最终目标(基本数学?统计数据?数据格式化?)。

答案 4 :(得分:0)

您可以使用csv模块和生成器阅读它:

import csv

def get_column(name):
    with open('filename', 'r') as handle:
        reader = csv.DictReader(handle, delimiter='\t')

        for row in reader:
            yield row[name]

但是一旦你开始用这些数据做一些事情,熊猫可能会更快。

答案 5 :(得分:-1)

def readAsCloumVec(fileName):
    reader = open(fileName,'r')
    text = reader.read()
    lines = text.split('\n')#Split the text into lines
    matrix = []
    for i in range(1,len(lines)):
        if(len(lines[i])>0):#Ignore the last useless line
            line = lines[i].split('\t')#The tag is depend on your file format
            matrix.append(line)
    cloumMatrix = []
    cloums = len(matrix[0])
    row = len(matrix)
    print  matrix    
    for j in range(cloums):#transposition the matrix
        cloum = []
        for i in range(row):            
            cloum.append(matrix[i][j])
        cloumMatrix.append(cloum)
    return cloumMatrix

if __name__ == "__main__":
    print readAsCloumVec('test.txt')