给定以下格式的制表符分隔文件,我需要以逐列方式执行操作。我知道的最简单的解决方案是使用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
如何通过只读一次整个文件来生成这些变量?
答案 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对象,那么肯定是,但可能不会使用pandas
或numpy
。
因此,您需要做的是将其从一种基于磁盘的格式转换为另一种格式,然后重写代码以便比原始文件更快地处理磁盘上的数据。
一个明显的可能性是您可以随机访问搜索或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
,或者只使用array
或pandas
来读取/写入每个(或可能只是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
应包含列标题的字符串键,每个键都指向该列中所有值的列表。
答案 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')