分块读取 Pandas 中的多个 CSV 文件
Posted
技术标签:
【中文标题】分块读取 Pandas 中的多个 CSV 文件【英文标题】:Read multiple CSV files in Pandas in chunks 【发布时间】:2019-07-26 00:39:46 【问题描述】:当我们有多个 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(已弃用)obj 有效”
有人可以帮忙吗?
【问题讨论】:
你试过df = pd.concat([pd.read_csv(f,sep=",",chunksize=10000) for f in allFiles])
。 IE。带方括号?我认为普通的括号给你一个发电机......
@mortysporty no 没有帮助。同样的错误
查看pd.read_csv
的文档似乎指定chunksize
参数会使方法调用返回一个TextFileReader
对象(而不是数据框),该对象必须被迭代。跨度>
如果您没有必要的 RAM 来保存所有块的结果,那么无论您是否以块的形式读取它都无关紧要......您仍然要让您的机器去繁荣......
@JonClements - 我有内存。只是它使这个读取过程非常缓慢并降低了性能
【参考方案1】:
一种方法是使用 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
【讨论】:
【参考方案2】:这是一个有趣的问题。我没有尝试过,但我认为代码看起来像下面的脚本。
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)
也许您可以将所有内容加载到内存中并直接处理,但处理所有内容可能需要更长的时间。
【讨论】:
【参考方案3】:要读取大型 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 个 csv,这可以正常工作。但在我的情况下,我的文件夹中有一堆 csv。所以 read_csv("file.csv") 在这里只使用 1 个文件但是我有一个包含很多 csv 文件的文件夹。这就是为什么在我的代码示例中连接它们 @pythonNinja 我建议您删除最多未用于机器学习的数据..我已经修改了我的程序以读取多个文件.. 谢谢,但是当我尝试连接数据时,我得到了同样的错误以上是关于分块读取 Pandas 中的多个 CSV 文件的主要内容,如果未能解决你的问题,请参考以下文章
pandas read_csv读取大文件的Memory error问题
使用分块将 CSV 文件读入 Pandas 数据帧,生成单个目标数据帧
Pandas:使用循环和分层索引将多个 csv 文件导入数据帧
如何在使用 pandas.read_csv 读取 csv 文件时将 pandas.dataframe 中的元素转换为 np.float?