【发布时间】:2013-11-30 18:44:59
【问题描述】:
我有一个 7GB csv 文件,我想将其拆分成更小的块,以便在笔记本上用 Python 进行分析时可读且速度更快。我想从中获取一小部分,大概 250MB,我该怎么做呢?
【问题讨论】:
我有一个 7GB csv 文件,我想将其拆分成更小的块,以便在笔记本上用 Python 进行分析时可读且速度更快。我想从中获取一小部分,大概 250MB,我该怎么做呢?
【问题讨论】:
您不需要 Python 来拆分 csv 文件。使用你的外壳:
$ split -l 100 data.csv
将data.csv 拆分为 100 行的块。
【讨论】:
split -l 100 data.csv data_split_的前缀文件中
我不得不做类似的任务,并使用了 pandas 包:
for i,chunk in enumerate(pd.read_csv('bigfile.csv', chunksize=500000)):
chunk.to_csv('chunk{}.csv'.format(i), index=False)
【讨论】:
chunksize 中指定的行数读取它。
这是我用来将文件 data.csv 拆分为多个 CSV 部分文件的小 Python 脚本。部分文件的数量可以通过chunk_size(每个部分文件的行数)来控制。
原始文件的标题行(列名)被复制到每个部分的 CSV 文件中。
它适用于大文件,因为它使用readline() 一次读取一行,而不是一次将整个文件加载到内存中。
#!/usr/bin/env python3
def main():
chunk_size = 9998 # lines
def write_chunk(part, lines):
with open('data_part_'+ str(part) +'.csv', 'w') as f_out:
f_out.write(header)
f_out.writelines(lines)
with open('data.csv', 'r') as f:
count = 0
header = f.readline()
lines = []
for line in f:
count += 1
lines.append(line)
if count % chunk_size == 0:
write_chunk(count // chunk_size, lines)
lines = []
# write remainder
if len(lines) > 0:
write_chunk((count // chunk_size) + 1, lines)
if __name__ == '__main__':
main()
【讨论】:
也许是这样的?
#!/usr/local/cpython-3.3/bin/python
import csv
divisor = 10
outfileno = 1
outfile = None
with open('big.csv', 'r') as infile:
for index, row in enumerate(csv.reader(infile)):
if index % divisor == 0:
if outfile is not None:
outfile.close()
outfilename = 'big-{}.csv'.format(outfileno)
outfile = open(outfilename, 'w')
outfileno += 1
writer = csv.writer(outfile)
writer.writerow(row)
【讨论】:
查看file对象上的Python docs(open(filename)返回的对象-您可以选择read指定的字节数,或使用readline一次处理一行。
【讨论】:
我同意@jonrsharpe readline 应该能够一次读取一行,即使对于大文件也是如此。
如果您正在处理大型 csv 文件,我建议您使用pandas.read_csv。我经常将它用于相同的目的,并且总是觉得它很棒(而且速度很快)。需要一些时间来习惯 DataFrames 的概念。但是一旦你克服了这一点,它就会大大加快像你这样的大型操作。
希望对您有所帮助。
【讨论】:
此图显示了其他海报概述的不同方法的运行时差异(在 8 核机器上,将具有 1180 万行数据的 2.9 GB 文件拆分为约 290 个文件)。
shell 方法来自 Thomas Orozco,Python 方法来自 Roberto,Pandas 方法来自 Quentin Febvre,这是 Dask sn-p:
ddf = dd.read_csv("../nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2015.csv", blocksize=10000000, dtype=dtypes)
ddf.to_csv("../tmp/split_csv_dask")
我推荐使用 Dask 来分割文件,尽管它不是最快的,因为它是最灵活的解决方案(您可以写出不同的文件格式、在写入之前执行处理操作、轻松修改压缩格式等)。 Pandas 方法几乎同样灵活,但无法对整个数据集进行处理(例如在写入之前对整个数据集进行排序)。
Bash / 本机 Python 文件系统操作显然更快,但这不是我在拥有大型 CSV 时通常要寻找的。我通常有兴趣将大型 CSV 拆分为更小的 Parquet 文件,以进行高性能的生产数据分析。我通常不在乎实际拆分是否需要几分钟。我对准确拆分更感兴趣。
我写了一篇博文,更详细地讨论了这个问题。您可能可以通过 Google 搜索并找到该帖子。
【讨论】: