我正在探索作为长期SAS用户切换到python和pandas。
但是,今天运行一些测试时,我很惊讶python在尝试pandas.read_csv()
128mb csv文件时内存不足。它有大约200,000行和200列主要是数字数据。
使用SAS,我可以将csv文件导入SAS数据集,它可以和我的硬盘一样大。
pandas
中有类似的东西吗?
我经常处理大型文件,无法访问分布式计算网络。
答案 0 :(得分:76)
原则上它不应该耗尽内存,但是由于一些复杂的Python内部问题导致大文件read_csv
存在内存问题(这很模糊,但很久以前就知道了:{ {3}})。
目前还没有一个完美的解决方案(这里很乏味:你可以逐行将文件转录到预先分配的NumPy数组或内存映射文件中 - np.mmap
),但这是我将在不久的将来开展的工作。另一个解决方案是以较小的块读取文件(使用iterator=True, chunksize=1000
),然后使用pd.concat
连接。当你将整个文本文件拉入内存时会出现问题。
答案 1 :(得分:75)
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`
答案 2 :(得分: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()
答案 3 :(得分: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')
根据您的文件大小,您最好优化chunksize。
for chunk in chunks:
chunk.to_sql(name='Table', if_exists='append', con=con)
count += 1
print(count)
在数据库中包含所有数据后,您可以从数据库中查询所需的数据。
答案 4 :(得分:3)
如果你想加载巨大的csv文件,dask可能是个不错的选择。它模仿了pandas api,所以感觉与pandas非常相似
答案 5 :(得分:1)
您可以使用Pytable而不是pandas df。 它专为大型数据集而设计,文件格式为hdf5。 因此处理时间相对较快。