将大型Pandas数据框以块的形式写入CSV文件

42

如何将大型数据文件分块写入CSV文件中?

我有一组大型数据文件(1M行×20列),但是只有其中约5个列对我有兴趣。

我想通过仅保留感兴趣的列来创建副本,以便我可以使用较小的文件进行后处理。因此,我的计划是将文件读入数据帧,然后写入CSV文件。

我一直在研究如何将大型数据文件分块读入数据帧中。然而,我还没有找到任何关于如何将数据分块写入CSV文件的信息。

以下是我现在正在尝试的代码,但这不会将CSV文件附加到已有的内容末尾:

with open(os.path.join(folder, filename), 'r') as src:
    df = pd.read_csv(src, sep='\t',skiprows=(0,1,2),header=(0), chunksize=1000)
    for chunk in df:
        chunk.to_csv(os.path.join(folder, new_folder,
                                  "new_file_" + filename), 
                                  columns = [['TIME','STUFF']])
3个回答

54

解决方法:

header = True
for chunk in chunks:

    chunk.to_csv(os.path.join(folder, new_folder, "new_file_" + filename),
        header=header, cols=[['TIME','STUFF']], mode='a')

    header = False

注意:

  • mode='a' 会告诉 pandas 进行追加操作。
  • 我们只在第一个块上写入列标题。

2
我注意到当我使用mode='a'进行追加时,列标签会在每个块后面写入。我该如何确保列标签仅出现在文件开头? - Korean_Of_the_Mountain
11
你可以将header=None传递给除第一个块以外的所有块。 - DG2
12
您可以使用 for i, chunk in chunks:,然后设置 header=(i==0)。该语句的作用是在处理分块数据时,在第一块数据前面添加一个标题行。 - naught101
我最终使用了这个解决方案和另一个解决方案,首先将数据框拆分成块:https://dev59.com/L2Qm5IYBdhLWcg3w0Bu5 - user3788120

22

请查看to_csv方法中的chunksize参数。这里是相关文档的链接

写入文件的代码如下:

df.to_csv("path/to/save/file.csv", chunksize=1000, cols=['TIME','STUFF'])

哎呀,我使用你提议的方法时遇到了以下错误:AttributeError: 'TextFileReader'对象没有属性'to_csv'。你的回答仍然假设我是按块读取"df"吗? - Korean_Of_the_Mountain
2
这是针对完整的DataFrame。 - Alex
1
当从一个文件流式传输大型数据帧时,这种方式并不可行,此时使用mode='a'更为合适。 - denfromufa
@denfromufa 确定吗?chunksize可能意味着分批写入,不是吗?然后它仍然必须以append模式完成。或者我错过了什么?虽然我不知道技术细节,但只是猜测。有人对此有更深入的了解吗?这里的情况是否与循环的已接受答案相同? - questionto42
我可以保证,在处理50 MB文件,700000行,块大小为5000的情况下,这种方法比普通的csv写入器循环批次要快得多。我没有检查过在接受的答案中以“append”模式循环数据框,但至少这个答案不会差。将云函数时间从之前的>9分钟超时限制降低到了62秒(我甚至不知道写入所有数据需要多长时间,但肯定更长)。 - questionto42

1
为什么不只读取感兴趣的列,然后保存它呢?
file_in = os.path.join(folder, filename)
file_out = os.path.join(folder, new_folder, 'new_file' + filename)

df = pd.read_csv(file_in, sep='\t', skiprows=(0, 1, 2), header=0, names=['TIME', 'STUFF'])
df.to_csv(file_out)

万一我遇到了太大而必须分块读取的文件,我不认为你的代码能够允许我这样做,对吧? - Korean_Of_the_Mountain
正确,但仍然更加高效。如果是这种情况,您仍需要分块或使用csv模块。 - Alexander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接