Pandas 中的大型持久 DataFrame
- 2025-02-25 09:07:00
- admin 原创
- 27
问题描述:
作为长期 SAS 用户,我正在探索转换到 python 和 pandas。
pandas.read_csv()
然而,今天运行一些测试时,我惊讶地发现,当尝试处理128mb 的 csv 文件时,python 内存不足。该文件有大约 200,000 行和 200 列,其中大部分是数字数据。
使用 SAS,我可以将 csv 文件导入 SAS 数据集,它可以和我的硬盘一样大。
有没有类似的东西pandas
?
我经常处理大型文件,但无法访问分布式计算网络。
解决方案 1:
Wes 当然是对的!我只是想提供一个更完整的示例代码。我遇到了一个 129 Mb 文件同样的问题,解决方法如下:
import pandas as pd
# Returns a TextFileReader, which is iterable with chunks of 1000 rows.
csv_iterator = pd.read_csv('large_dataset.csv', iterator=True, chunksize=1000)
# Iterate through the dataframe chunks and print one row/record at a time
for chunk in csv_iterator:
for index, row in chunk.iterrows():
print(row)
# df is DataFrame. If errors, use `list(csv_iterator)` instead
df = pd.concat(tp, ignore_index=True)
解决方案 2:
原则上它不应该耗尽内存,但read_csv
由于一些复杂的 Python 内部问题(这一点很模糊,但早已为人所知:http://github.com/pydata/pandas/issues/407),目前在处理大文件时存在内存问题。
目前还没有完美的解决方案(这里有一个冗长乏味的解决方案:你可以将文件逐行转录到预分配的 NumPy 数组或内存映射文件中—— np.mmap
),但我将在不久的将来研究它。另一个解决方案是将文件分成较小的部分(使用iterator=True, chunksize=1000
),然后将其与连接起来pd.concat
。当你将整个文本文件一次性拉入内存时,问题就出现了。
解决方案 3:
这是一个较旧的线程,但我只是想在这里转储我的解决方法。我最初尝试了该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:
以下是我的工作流程。
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)
数据库中有了所有数据后,您就可以从数据库中查询出您需要的数据。
解决方案 5:
如果你想加载巨大的 csv 文件,dask 可能是一个不错的选择。它模仿了 pandas api,所以感觉和 pandas 很相似
链接到 github 上的 dask
解决方案 6:
您可以使用 Pytable 而不是 pandas df。它是为大型数据集设计的,文件格式为 hdf5。因此处理时间相对较快。