我正在探索作爲長期SAS用戶切換到python和pandas。熊貓中的大型持久數據框
但是,今天在運行一些測試時,我驚訝於python在嘗試pandas.read_csv()
128mb csv文件時內存不足。它有大約20萬行和200列的大部分數字數據。
使用SAS,我可以將csv文件導入到SAS數據集中,並且可以像我的硬盤一樣大。
pandas
是否有類似的東西?
我經常使用大型文件,無法訪問分佈式計算網絡。
我正在探索作爲長期SAS用戶切換到python和pandas。熊貓中的大型持久數據框
但是,今天在運行一些測試時,我驚訝於python在嘗試pandas.read_csv()
128mb csv文件時內存不足。它有大約20萬行和200列的大部分數字數據。
使用SAS,我可以將csv文件導入到SAS數據集中,並且可以像我的硬盤一樣大。
pandas
是否有類似的東西?
我經常使用大型文件,無法訪問分佈式計算網絡。
原則上它不應該耗盡內存,但目前由於一些複雜的Python內部問題(這是模糊的,但已知很長時間:http://github.com/pydata/pandas/issues/407)導致的大文件上存在read_csv
內存問題。
目前還沒有一個完美的解決方案(這裏是一個單調乏味的解決方案:您可以逐行將文件轉錄成預分配的NumPy數組或內存映射文件 - np.mmap
),但它是一個我會在不久的將來努力。另一種解決方案是以較小的文件讀取文件(使用iterator=True, chunksize=1000
),然後與pd.concat
連接。當你將整個文本文件拖入內存時,問題就出現了。
說我可以讀取文件並將它們全部連接成一個DataFrame。 DataFrame是否必須駐留在內存中?藉助SAS,只要具有硬盤空間,我就可以處理任何大小的數據集。它與DataFrames相同嗎?我得到的印象是受RAM限制,而不是硬盤空間。對不起noob問題,並感謝您的幫助。我很喜歡你的書。 – Zelazny7 2012-07-24 01:46:02
對,你受到內存的限制。 SAS確實對「非核心」大數據處理提供了更好的支持。 – 2012-07-24 04:12:59
@WesMcKinney由於你登陸0.10的新csv加載器,不應再需要這些變通辦法了,對嗎? – 2013-07-29 11:44:40
韋斯當然是對的!我只是想提供一些更完整的示例代碼。我有同樣的問題與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`
這是一個較舊的線程,但我只是想在這裏傾倒我的解決方法解決方案。我最初嘗試chunksize
參數(即使像10000這樣的相當小的值),但它沒有多大幫助;內存大小仍然存在技術問題(我的CSV是〜7.5 Gb)。
現在,我剛纔讀的CSV文件的數據塊在for循環的方法,並逐步將它們添加例如,一個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-06-30 16:37:37
這個老話題:只要提供'iterator = True'和'chunksize = chunksize','pandas.read_csv'就會直接返回(至少在我目前使用的版本上)一個迭代器。因此,您只需對'pd.read_csv'調用執行'for'循環,而不是每次都重新實例化它。但是,這隻需花費通話費用,可能沒有重大影響。 – 2015-12-08 15:19:29
嗨,喬爾。謝謝你的提示!如果我沒有記錯,那麼'iterator = True'和'chunksize'參數已經存在。也許在舊版本中存在一個導致內存爆炸的bug - 下次我在Pandas中讀取一個大型DataFrame時,我會再試一次(我現在主要使用Blaze來完成這些任務) – Sebastian 2015-12-08 18:57:09
您可以使用Pytable而不是熊貓DF。 它設計用於大型數據集,文件格式爲hdf5。 所以處理時間相對較快。
以下是我的工作流程。
import sqlalchemy as sa
import pandas as pd
import psycopg2
count = 0
con = sa.create_engine('postgresql://postgres:[email protected]: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)
在數據庫中有所有數據後,您可以從數據庫中查詢出您需要的數據。
如果你想加載巨大的csv文件,dask可能是一個不錯的選擇。它模仿大熊貓的API,所以感覺非常相似,大熊貓
謝謝,自從我發佈以來這我一直在使用dask和鑲木地板格式。 – Zelazny7 2017-06-09 02:32:58
我不熟悉的大熊貓,但你可能想通過通過文件迭代的樣子。 http://pandas.pydata.org/pandas-docs/stable/io。html#iterating-through-files-chunk-by-chunk – monkut 2012-07-24 01:02:08