【问题标题】:Divide .csv file into chunks with Python使用 Python 将 .csv 文件分成块
【发布时间】:2015-12-20 23:26:08
【问题描述】:

我有一个超过 300 GB 的大型 .csv 文件。我想将它分块为每个 100,000,000 行的较小文件(每行大约有 55-60 个字节)。

我写了以下代码:

import pandas as pd
df = pd.read_csv('/path/to/really/big.csv',header=None,chunksize=100000000)
count = 1
for chunk in df:
    name = '/output/to/this/directory/file_%s.csv' %s count
    chunk.to_csv(name,header=None,index=None)
    print(count)
    count+=1

这段代码运行良好,我在磁盘上有足够的内存一次存储大约 5.5-6 GB,但它

有没有更好的办法?

编辑

我已经编写了以下迭代解决方案:

with open('/path/to/really/big.csv', 'r') as csvfile:
    read_rows = csv.reader(csvfile)
    file_count = 1
    row_count = 1
    f = open('/output/to/this/directory/file_%s.csv' %s count,'w')
    for row in read_rows:
        f.write(''.join(row))
        row_count+=1
        if row_count % 100000000 == 0:
            f.close()
            file_count += 1
            f = open('/output/to/this/directory/file_%s.csv' %s count,'w')

编辑 2

我想提请注意 Vor 关于使用 Unix/Linux 拆分命令的评论,这是我找到的最快的解决方案。

【问题讨论】:

  • 无需重新发明轮子使用 split linux.die.net/man/1/split 。如果你确实想要它在 python 中,那么将 if 包装在 subprocess 模块中。
  • 我也一定会试一试的!
  • 为什么还要使用 csv 模块?你只是在读和写行。行的输入和输出格式保持不变。另外,for row in read_rows 可以是for row_count, row in enumerate(read_rows, start=1),这样就不需要跟踪行号了。

标签: python csv pandas


【解决方案1】:

在 Unix/Linux 中有一个现有的工具。

split -l 100000 -d source destination

将为块的目标前缀添加两位数字后缀。

【讨论】:

    【解决方案2】:

    您实际上并不需要将所有数据读入 pandas DataFrame 来分割文件 - 您甚至根本不需要将数据全部读入内存。您可以寻找要拆分的近似偏移量,然后向前扫描,直到找到换行符,然后循环从源文件中读取更小的块到您的开始和结束偏移量之间的目标文件中。 (此方法假定您的 CSV 没有任何带有嵌入换行符的列值。)

    SMALL_CHUNK = 100000
    
    def write_chunk(source_file, start, end, dest_name):
        pos = start
        source_file.seek(pos)
        with open(dest_name, 'w') as dest_file:
            for chunk_start in range(start, end, SMALL_CHUNK):
                chunk_end = min(chunk_start + SMALL_CHUNK, end)
                dest_file.write(source_file.read(chunk_end - chunk_start))
    

    实际上,一个中间解决方案可能是使用csv 模块——它仍然会解析文件中的所有行,这不是绝对必要的,但可以避免将巨大的数组读取到每个块的内存中。

    【讨论】:

    • 我猜 Pandas 会原生处理这个问题?我对熊猫一点也不熟悉。那么您是否同意我发布的关于使用生成器的解决方案在这种情况下无效?
    • 您的答案依赖于将所有行都保存在内存中,这对于正在处理的大文件调用程序来说是不可行的。
    • 好的。看来我在这里也学到了一些东西。 :) 谢谢。我将删除我的解决方案。
    • 我喜欢这个,你知道它相对于读入内存或只是迭代的表现如何?我刚刚写了另一个我正在运行的代码的 sn-p 迭代,我将把它放在上面的编辑中。
    • 我没有进行基准测试,但我希望它会更快 - 它不需要将每一行解析为列表,只需在每次大跳转时扫描下一行边界(其中不会花很长时间,因为每行只有约 60 个字节)。
    猜你喜欢
    • 1970-01-01
    • 2019-03-14
    • 2019-04-13
    • 2015-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多