我有一个很大的.csv文件,大小超过300 GB。我想将其分块成每个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
Run Code Online (Sandbox Code Playgroud)
这段代码可以正常工作,并且我在磁盘上有足够的内存来一次存储大约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')
Run Code Online (Sandbox Code Playgroud)
编辑2
我想提请注意Vor关于使用Unix / Linux split命令的评论,这是我找到的最快的解决方案。
在Unix / Linux中,已有一个用于此目的的工具。
split -l 100000 -d source destination
Run Code Online (Sandbox Code Playgroud)
会将两位数字的数字后缀添加到块的目标前缀。
您实际上并不需要将所有数据读入 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))
Run Code Online (Sandbox Code Playgroud)
实际上,中间解决方案可能是使用该csv模块 - 它仍然会解析文件中的所有行,这并不是严格必要的,但可以避免将每个块的巨大数组读入内存。
| 归档时间: |
|
| 查看次数: |
4658 次 |
| 最近记录: |