熊猫中的大型持久性DataFrame


91

我正在探索以长期的SAS用户身份切换到python和pandas的问题。

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

使用SAS,我可以将csv文件导入SAS数据集,并且该文件可以与硬盘一样大。

有类似的东西pandas吗?

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


我对熊猫不熟悉,但是您可能需要遍历文件。 pandas.pydata.org/pandas-docs/stable/...
monkut

Answers:


79

原则上,它不应该用完内存,但是read_csv由于一些复杂的Python内部问题,当前存在大文件上的内存问题(这是模糊的,但已经有很长时间了:http : //github.com/pydata / pandas / issues / 407)。

目前还没有一个完美的解决方案(这是一个单调乏味的解决方案:您可以将文件逐行转录为预先分配的NumPy数组或内存映射文件- np.mmap),但这是我将要使用的解决方案。在不久的将来。另一种解决方案是先读取文件(使用iterator=True, chunksize=1000),然后再使用进行连接pd.concat。当您将整个文本文件拖入内存时,就会出现问题。


1
说我可以读取文件并将它们全部合并到一个DataFrame中。DataFrame是否必须驻留在内存中?使用SAS,只要有硬盘空间,我就可以处理任何大小的数据集。DataFrames是否一样?我觉得它们受RAM限制,而不是硬盘空间。很抱歉出现菜鸟问题,感谢您的帮助。我很喜欢你的书。
Zelazny12年

3
是的,您受制于RAM。SAS确实为“核心外”大数据处理提供了更好的支持。
Wes McKinney

5
@WesMcKinney不再需要这些解决方法,因为您将新的csv加载程序放入了0.10中,对吗?
加百利·格兰特

79

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

import pandas as pd

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

6
我想你能做到df = concate(tp, ignore_index=True)吗?
安迪·海登

@smci使用重复的x4(550 Mb)或x8(1.1Gb)的相同数据快速尝试了此操作。有趣的是,无论是否使用[x for tp中的x],x4都可以正常运行,并且x8在MemoryError中崩溃。
fickludd

3
使用时出现此错误:AssertionError: first argument must be a list-like of pandas objects, you passed an object of type "TextFileReader"。知道这里发生了什么吗?
库玛亲王

3
该错误将在0.14(即将发布)中修复github.com/pydata/pandas/pull/6941 ; <0.14.0的解决方法是要做的pd.concat(list(tp), ignore_index=True)
Jeff

1
如果值是字符串还是分类的,该怎么办-我遇到错误:分类连接中的类别不兼容
As3adTintin 2015年

41

这是一个较旧的线程,但是我只想在这里转储我的解决方法。最初,我尝试了该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()    

4
超级有用,可以查看分块阅读功能的实际用例。谢谢。
Alex Kestner

5
只是对这个旧主题的一小段话:pandas.read_csv如果仅提供iterator=Trueand,则直接返回(至少在我当前使用的版本上)迭代器chunksize=chunksize。因此,您只需要forpd.read_csv调用进行循环,而不必每次都重新实例化。但是,这仅花费了呼叫开销,可能不会产生重大影响。
2015年

1
嗨,乔尔。感谢您的来信!如果我没记错的话,iterator=Truechunksize参数早已存在。也许是较旧版本中的一个错误导致了内存耗尽-下次我在Pandas中读取大型DataFrame时,我将再次尝试(我现在主要是在使用Blaze来执行此类任务)

6

以下是我的工作流程。

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')

根据文件大小,最好对块大小进行优化。

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

将所有数据存储在数据库中之后,您可以从数据库中查询出所需的数据。


3

如果您想加载巨大的csv文件,则dask可能是一个不错的选择。它模仿了熊猫API,所以感觉和熊猫很相似

链接到github上的dask


谢谢,自从我发布此文章以来,我一直在使用dask和镶木地板格式。
Zelazny17年7

1

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.