首页 文章

pandas中的大型持久DataFrame

提问于
浏览
83

我正在探索作为长期SAS用户切换到python和pandas .

但是,今天运行一些测试时,我很惊讶python在尝试 pandas.read_csv() 一个128mb的csv文件时内存不足 . 它有大约200,000行和200列主要是数字数据 .

使用SAS,我可以将csv文件导入SAS数据集,它可以和我的硬盘一样大 .

pandas 中有类似的东西吗?

我经常处理大型文件,无法访问分布式计算网络 .

6 回答

  • 36

    原则上它不应该耗尽内存,但是由于一些复杂的Python内部问题导致大文件上存在 read_csv 的内存问题(这很模糊,但很久以来就已经知道了:http://github.com/pydata/pandas/issues/407) .

    目前还没有一个单调乏味的文件:你可以逐行将文件转录到预先分配的NumPy数组或内存映射文件中 - np.mmap ),但它会在不久的将来继续工作 . 另一种解决方案是以较小的块读取文件(使用 iterator=True, chunksize=1000 ),然后使用 pd.concat 连接 . 当你将整个文本文件拉入内存时会出现问题 .

  • 1

    Wes当然是对的!我只是想提供一些更完整的示例代码 . 我遇到了129 Mb文件的相同问题,该文件通过以下方式解决:

    from pandas import *
    
    tp = read_csv('large_dataset.csv', iterator=True, chunksize=1000)  # gives TextFileReader, which is iterable with chunks of 1000 rows.
    df = concat(tp, ignore_index=True)  # df is DataFrame. If errors, do `list(tp)` instead of `tp`
    
  • 73

    这是一个较旧的线程,但我只是想在此处转储我的解决方案 . 我最初尝试了 chunksize 参数(即使是像10000这样的非常小的值),但它没有多大帮助;还有内存大小的技术问题(我的CSV是~7.5 Gb) .

    现在,我只是以for循环方式读取CSV文件的块,并将它们逐步添加到SQLite数据库中:

    import pandas as pd
    import sqlite3
    from pandas.io import sql
    import subprocess
    
    # In and output file paths
    in_csv = '../data/my_large.csv'
    out_sqlite = '../data/my.sqlite'
    
    table_name = 'my_table' # name for the SQLite database table
    chunksize = 100000 # number of lines to process at each iteration
    
    # columns that should be read from the CSV file
    columns = ['molecule_id','charge','db','drugsnow','hba','hbd','loc','nrb','smiles']
    
    # Get number of lines in the CSV file
    nlines = subprocess.check_output('wc -l %s' % in_csv, shell=True)
    nlines = int(nlines.split()[0]) 
    
    # connect to database
    cnx = sqlite3.connect(out_sqlite)
    
    # Iteratively read CSV and dump lines into the SQLite table
    for i in range(0, nlines, chunksize):
    
        df = pd.read_csv(in_csv,  
                header=None,  # no header, define column header manually later
                nrows=chunksize, # number of rows to read at each iteration
                skiprows=i)   # skip rows that were already read
    
        # columns to read        
        df.columns = columns
    
        sql.to_sql(df, 
                    name=table_name, 
                    con=cnx, 
                    index=False, # don't use CSV file index
                    index_label='molecule_id', # use a unique column from DataFrame as index
                    if_exists='append') 
    cnx.close()
    
  • 73

    以下是我的工作流程 .

    import sqlalchemy as sa
    import pandas as pd
    import psycopg2
    
    count = 0
    con = sa.create_engine('postgresql://postgres:pwd@localhost:00001/r')
    #con = sa.create_engine('sqlite:///XXXXX.db') SQLite
    chunks = pd.read_csv('..file', chunksize=10000, encoding="ISO-8859-1",
                         sep=',', error_bad_lines=False, index_col=False, dtype='unicode')
    

    根据您的文件大小,您最好优化chunksize .

    for chunk in chunks:
            chunk.to_sql(name='Table', if_exists='append', con=con)
            count += 1
            print(count)
    

    在数据库中包含所有数据后,您可以从数据库中查询出您需要的数据 .

  • 3

    如果你想加载巨大的csv文件,dask可能是一个不错的选择 . 它模仿熊猫api,所以它感觉与熊猫非常相似

    link to dask on github

  • 3

    你可以使用Pytable而不是pandas df . 它专为大型数据集而设计,文件格式为hdf5 . 因此处理时间相对较快 .

相关问题