96

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

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

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

有类似的东西pandas吗?

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

4

6 回答 6

84

韦斯当然是对的!我只是想提供一些更完整的示例代码。我对一个 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`
于 2012-08-30T08:57:26.267 回答
82

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

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

于 2012-07-24T01:10:50.813 回答
43

这是一个较旧的线程,但我只是想在这里转储我的解决方法。我最初尝试了这个chunksize参数(即使是非常小的值,比如 10000),但它并没有太大帮助;内存大小仍然存在技术问题(我的 CSV 约为 7.5 Gb)。

现在,我只是在 for-loop 方法中读取 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()    
于 2015-02-06T17:46:34.837 回答
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)

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

于 2017-05-19T21:29:16.783 回答
4

如果你想加载巨大的 csv 文件,dask 可能是一个不错的选择。它模仿了pandas api,所以感觉很像pandas

链接到 github 上的 dask

于 2017-06-08T21:54:47.390 回答
1

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

于 2017-02-10T17:38:48.293 回答