加快了约50GB CSV文件的轻处理速度



我有一个大约50GB的csv文件,我必须使用它进行

  • 取CSV列的几个子集
  • 将不同的格式字符串规范应用于CSV的每个列子集
  • 为每个子集输出一个具有自己格式规范的新CSV

我选择了使用Pandas,并有一种通用的方法,即迭代一个方便的块大小(刚刚超过50万行)的块来生成DataFrame,并将块附加到每个输出CSV。这样的东西:

_chunk_size = 630100
column_mapping = {
    'first_output_specification' : ['Scen', 'MS', 'Time', 'CCF2', 'ESW10'],
    # ..... similar mappings for rest of output specifications
}
union_of_used_cols = ['Scen', 'MS', 'Time', 'CCF1', 'CCF2', 'VS', 'ESW 0.00397', 'ESW0.08',
                    'ESW0.25', 'ESW1', 'ESW 2', 'ESW3', 'ESW 5', 'ESW7', 'ESW 10', 'ESW12',
                    'ESW 15', 'ESW18', 'ESW 20', 'ESW22', 'ESW 25', 'ESW30', 'ESW 35', 
                    'ESW40']
chnk_iter = pd.read_csv('my_big_csv.csv', header=0, index_col=False,
                        iterator=True, na_filter=False, usecols=union_of_used_cols)
cnt = 0
while cnt < 100:
    chnk = chnk_iter.get_chunk(_chunk_size)
    chnk.to_csv('first_output_specification', float_format='%.8f',
                columns=column_mapping['first_output_specification'],
                mode='a',
                header=True,
                index=False)
    # ..... do the same thing for the rest of the output specifications
    cnt += 1

我的问题是这真的很慢。每个区块大约需要一分钟的时间来生成附加到的CSV文件,因此我需要将近2个小时才能完成任务。

我尝试过在读取CSV时只使用列子集的并集以及设置na_filter=False来进行一些优化,但这仍然是不可接受的。

我想知道是否有一种更快的方法可以在Python中轻松处理CSV文件,要么通过优化或更正我的方法,要么只是有一种比Pandas更适合这种工作的工具。。。对我(一个没有经验的Pandas用户)来说,这看起来像是Pandas的速度,但我很可能错了。

我不认为您从Panda的数据帧中获得任何优势,所以它只是增加了开销。相反,您可以使用python自己的CSV模块,该模块易于使用,并在C.中进行了很好的优化

考虑将更大的块读取到内存中(一次可能为10MB),然后在前进到下一个块之前写出每个重新格式化的列子集。这样,输入文件只会被读取和解析一次。

您可以尝试的另一种方法是使用Unixcut命令预处理数据,只提取相关列(这样Python就不必为未使用的列中的数据创建对象和分配内存):cut -d, -f1,3,5 somedata.csv

最后,尝试在PyPy下运行代码,以便通过跟踪JIT优化脚本的CPU绑定部分。

我会尝试使用python csv模块和生成器。

我发现生成器在解析巨大的服务器日志等方面比其他方法快得多。

import csv
def reader(csv_filename):
    with open(csv_filename, 'r') as f:
        csvreader = csv.reader(f, delimiter=',', quotechar="'")
        for line in csvreader:
            yield line  # line is a tuple
def formatter(lines):
    for line in lines:
        # format line according to specs
        yield formatted_line
def write(lines, csv_filename):
    with open(csv_filename, 'w') as f:
        writer = csv.writer(f)
        for line in lines:
            writer.writerow(line)
 lines = reader('myfile.in.csv')
 formatted_lines = formatter(lines)
 write(formatted_lines, 'myfile.out.csv')

这只是为了读取将单个输入csv转换为单个输出csv的文件,但您可以编写格式化程序和编写器来输出多个文件。

(我现在看到这个问题已经一个月了-不确定你是否已经解决了你的问题-如果没有,如果你想要更详细的解释/例子,请告诉我。)

CPU比磁盘访问更快。一个技巧是用gzip压缩你的文件并从中读取。

import gzip
with gzip.open('input.gz','r') as fin:
    for line in fin:
        print('got line', line)

相关内容

  • 没有找到相关文章

最新更新