【问题标题】:Read multiple CSV files in Pandas in chunks分块读取 Pandas 中的多个 CSV 文件
【发布时间】: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 - 我有内存。只是它使这个读取过程非常缓慢并降低了性能

标签: python pandas jupyter-notebook sklearn-pandas


【解决方案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 我建议您删除最多未用于机器学习的数据..我已经修改了我的程序以读取多个文件..
      • 谢谢,但是当我尝试连接数据时,我得到了同样的错误
      猜你喜欢
      • 1970-01-01
      • 2022-11-03
      • 1970-01-01
      • 1970-01-01
      • 2016-03-15
      • 1970-01-01
      • 2022-01-25
      • 2020-04-29
      • 2017-06-09
      相关资源
      最近更新 更多