pandas中的大型持久性DataFrame

Zel*_*ny7 88 python sas pandas

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

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

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

有类似的东西pandas吗?

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

Wes*_*ney 77

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

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

  • @WesMcKinney这些变通办法不再需要了,因为新的csv加载器你降落在0.10,对吗? (5认同)
  • 对,你受RAM限制.SAS确实对"核外"大数据处理提供了更好的支持. (3认同)

fic*_*udd 76

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`
Run Code Online (Sandbox Code Playgroud)

  • 我想你可以做`df = concate(tp,ignore_index = True)`? (6认同)
  • 我在使用它时遇到这个错误:`AssertionError:第一个参数必须是类似于pandas对象的列表,你传递了一个类型为"TextFileReader"的对象.知道这里发生了什么吗? (3认同)
  • 此错误将在0.14(即将发布)中修复,https://github.com/pydata/pandas/pull/6941; <0.14.0的解决方法是``pd.concat(list(tp),ignore_index = True)`` (3认同)

小智 38

这是一个较旧的线程,但我只想在此处转储我的解决方案.我最初尝试了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()    
Run Code Online (Sandbox Code Playgroud)

  • 对于这个古老的话题只是一个小小的评论:`pandas.read_csv`如果只提供`iterator = True`和`chunksize = chunksize`,则直接返回(至少在我当前使用的版本上)迭代器.因此,您只需在`pd.read_csv`调用上执行`for`循环,而不是每次都重新实例化它.但是,这仅花费了呼叫开销,可能没有重大影响. (5认同)
  • 查看分块阅读功能的实际用例非常有用.谢谢. (4认同)

WeN*_*Ben 5

以下是我的工作流程.

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')
Run Code Online (Sandbox Code Playgroud)

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

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

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