如何在Python中转置/透视CSV文件,而不将整个文件加载到内存中?

1 投票
5 回答
3237 浏览
提问于 2025-04-17 00:09

在我的一个数据分析流程中,我会生成很多单独的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”的方式来读取每一行。

撰写回答