当我们有多个csv文件且所有csv的总大小约为20gb时,如何分块导入和读取多个CSV?
我不想使用Spark
,因为我想在SkLearn中使用模型,所以我想要Pandas
本身的解决方案。
我的代码是:
allFiles = glob.glob(os.path.join(path, "*.csv"))
df = pd.concat((pd.read_csv(f,sep=",") for f in allFiles))
df.reset_index(drop=True, inplace=True)
但是这失败了,因为我的路径中所有csv的总大小为17gb。
我想分块阅读它,但是如果尝试这样会出现一些错误:
allFiles = glob.glob(os.path.join(path, "*.csv"))
df = pd.concat((pd.read_csv(f,sep=",",chunksize=10000) for f in allFiles))
df.reset_index(drop=True, inplace=True)
我得到的错误是:
“无法连接类型为“”的对象;只有pd.Series,pd.DataFrame和pd.Panel(已弃用)objs有效”
有人可以帮忙吗?
答案 0 :(得分:0)
要读取较大的csv文件,可以使用chunksize,但在这种情况下,您必须像这样使用迭代器:
for df in pd.read_csv('file.csv', sep=',', iterator=True, chunksize=10000):
process(df)
您必须合并或附加每个块
或者您可以这样做:
df = pd.read_csv('file.csv',, sep=',', iterator=True, chunksize=10000)
for chunk in df:
process(chunk)
读取多个文件:例如
listfile = ['file1,'file2]
dfx = pd.DataFrame()
def process(d):
#dfx=dfx.append(d) or dfx = pd.concat(dfx, d)
#other coding
for f in listfile:
for df in pd.read_csv(f, sep=',', iterator=True, chunksize=10000):
process(df)
拥有大量文件后,您可以使用多处理库中的DASK或Pool启动大量读取过程
无论如何,要么您有足够的内存,要么浪费时间
答案 1 :(得分:0)
这是一个有趣的问题。我没有尝试过,但是我认为代码看起来像下面的脚本。
import pandas as pd
import csv
import glob
import os
#os.chdir("C:\\your_path\\")
results = pd.DataFrame([])
filelist = glob.glob("C:\\your_path\\*.csv")
#dfList=[]
for filename in filelist:
print(filename)
namedf = pd.read_csv(filename, skiprows=0, index_col=0)
results = results.append(namedf)
results.to_csv('C:\\your_path\\Combinefile.csv')
chunksize = 10 ** 6
for chunk in pd.read_csv('C:\\your_path\\Combinefile.csv', chunksize=chunksize):
process(chunk)
也许您可以将所有内容加载到内存中并直接对其进行处理,但是处理所有内容可能会花费更长的时间。
答案 2 :(得分:0)
执行此操作的一种方法是使用pd.read_csv(file,chunksize = chunksize)对数据帧进行分块,然后,如果您读取的最后一个块短于块大小,请保存多余的位,然后将其添加到第一个下一块的文件。
但是请确保读取下一个文件的较小的第一块,使其等于总块大小。
def chunk_from_files(dir, master_chunksize):
'''
Provided a directory, loops through files and chunks out dataframes.
:param dir: Directory to csv files.
:param master_chunksize: Size of chunk to output.
:return: Dataframes with master_chunksize chunk.
'''
files = os.listdir(dir)
chunksize = master_chunksize
extra_chunk = None # Initialize the extra chunk.
for file in files:
csv_file = os.path.join(dir, file)
# Alter chunksize if extra chunk is not None.
if extra_chunk is not None:
chunksize = master_chunksize - extra_chunk.shape[0]
for chunk in pd.read_csv(csv_file, chunksize=chunksize):
if extra_chunk is not None:
# Concatenate last small chunk of previous file with altered first chunk of next file.
chunk = pd.concat([chunk, extra_chunk])
extra_chunk = None
chunksize = master_chunksize # Reset chunksize.
elif chunk.shape[0] < chunksize:
# If last chunk is less than chunk size, set is as the extra bit.
extra_chunk = chunk
break
yield chunk