如何在Python中转置/透视CSV文件,而不将整个文件加载到内存中?
在我的一个数据分析流程中,我会生成很多单独的CSV文件。我想把这些文件的内容进行转置、合并,然后再转置一次。不过,由于数据量很大,把所有数据一次性加载到内存中是不现实的。
5 个回答
1
如果你想把两个csv文件里的数据行连接起来,而不把它们全部加载到内存中,这其实是个相对简单又快速的操作:只需从每个文件中读取一行,把这两行连接在一起,然后写入到一个输出文件中,重复这个过程直到所有输入数据都处理完。
而如果你想把csv文件里的数据进行转置,但又不想把整个文件加载到内存中,这个过程会慢很多,因为你需要多次读取整个输入文件,每次只提取其中的一列数据。如果这样做是可以接受的(或者是必须的),那么使用内置的 csv
模块大致可以这样进行:
import csv
input_filename = 'input.csv'
output_filename = 'output.csv'
with open(output_filename, 'wb') as outputf:
writer = csv.writer(outputf)
with open(input_filename, 'rb') as inputf:
# determine number of columns in input file by counting those in its first row
# number of cols in input file determines number of rows in output file
numcols = len(csv.reader(inputf).next())
# read entire input file multiple times, extracting one column from each row
for col_index in xrange(numcols):
# write all of column data as a single row of the output file
inputf.seek(0) # rewind file for each pass
writer.writerow(tuple(row[col_index] for row in csv.reader(inputf)))
2
这是一个简短而且很“python风”的解决方案。我用这个方法来转置一些有1500万行和12000列的CSV文件。速度很快,而且完全是用Python写的。其他需要做的事情都很简单,而这绝对是最难的部分。
GitHub链接: https://gist.github.com/arose13/facfb91b609d453f3ad840417faa503a
def transpose_csv_out_of_core(csv_path, output_csv_path='transposed.csv', delimiter=','):
"""
On my laptop it can transpose at ~375,000 lines a sec
:param csv_path:
:param output_csv_path:
:param delimiter:
:return:
"""
import csv
transposed_iterator = zip(*csv.reader(open(csv_path)))
with open(output_csv_path, 'w') as out:
for row in transposed_iterator:
out.write(delimiter.join(row) + '\n')
-1
使用生成器,比如:
from itertools import izip
file1 = open("test", "r")
file2 = open("test2", "r")
def lazy(file):
for line in file:
#do something with the line
yield line
for lines in izip(lazy(file1), lazy(file2)):
print lines
http://wiki.python.org/moin/Generators
补充:你可以使用CSV模块来解析它。另外,我发现文件对象的readlines()方法并不是懒加载的,所以你需要用“for line in file”的方式来读取每一行。