[英]Sequentially read huge CSV file in python
我有一個10gb的CSV文件,其中包含一些我需要使用的信息。
由於我的PC上的內存有限,因此無法單批讀取內存中的所有文件。 相反,我只想迭代讀取此文件的某些行。
假設在第一次迭代時我想讀取前100個,在第二次迭代中要讀取101到200,依此類推。
有沒有一種有效的方法可以在Python中執行此任務? 熊貓可以提供一些有用的東西嗎? 還是有更好的方法(在內存和速度方面)?
這是簡短的答案。
chunksize = 10 ** 6
for chunk in pd.read_csv(filename, chunksize=chunksize):
process(chunk)
這是很長的答案。
首先,您需要導入pandas和sqlalchemy。 下面的命令將執行此操作。
import pandas as pd
from sqlalchemy import create_engine
接下來,設置一個指向您的csv文件的變量。 這不是必需的,但確實有助於重用。
file = '/path/to/csv/file'
有了這三行代碼,我們就可以開始分析數據了。 讓我們看一下csv文件的“頭”,看看內容可能是什么樣子。
print pd.read_csv(file, nrows=5)
此命令使用pandas的“ read_csv”命令僅讀取5行(行數= 5),然后將這些行打印到屏幕上。 這使您了解csv文件的結構,並確保以對您的工作有意義的方式格式化數據。
在實際使用數據之前,我們需要對其進行處理,以便可以開始對其進行過濾以與數據的子集一起使用。 這通常是我將使用pandas數據框的方式,但是對於大型數據文件,我們需要將數據存儲在其他位置。 在這種情況下,我們將建立一個本地sqllite數據庫,分塊讀取csv文件,然后將這些塊寫入sqllite。
為此,我們首先需要使用以下命令創建sqllite數據庫。
csv_database = create_engine('sqlite:///csv_database.db')
接下來,我們需要分批遍歷CSV文件並將數據存儲到sqllite中。
chunksize = 100000
i = 0
j = 1
for df in pd.read_csv(file, chunksize=chunksize, iterator=True):
df = df.rename(columns={c: c.replace(' ', '') for c in df.columns})
df.index += j
i+=1
df.to_sql('table', csv_database, if_exists='append')
j = df.index[-1] + 1
使用此代碼,我們將塊大小設置為100,000,以保持可管理的塊大小,並初始化幾個迭代器(i = 0,j = 0),然后運行一個for循環。 for循環從CSV文件中讀取數據塊,從任何列名稱中刪除空間,然后將數據塊存儲到sqllite數據庫(df.to_sql(…))中。
如果您的CSV文件足夠大,則可能要花一些時間,但是花在等待上的時間是值得的,因為您現在可以使用pandas“ sql”工具從數據庫中提取數據,而不必擔心內存限制。
要立即訪問數據,您可以運行以下命令:
df = pd.read_sql_query('SELECT * FROM table', csv_database)
當然,使用“ select *…”會將所有數據加載到內存中,這是我們試圖解決的問題,因此您應該將過濾器放入select語句中以過濾數據。 例如:
df = pd.read_sql_query('SELECT COl1, COL2 FROM table where COL1 = SOMEVALUE', csv_database)
您可以將pandas.read_csv()
與chuncksize
參數一起使用:
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html#pandas.read_csv
for chunck_df in pd.read_csv('yourfile.csv', chunksize=100):
# each chunck_df contains a part of the whole CSV
將巨大的CSV傳輸到數據庫的方法很好,因為我們可以輕松地使用SQL查詢。 我們還必須考慮兩件事。
第一要點: SQL也不是橡皮筋,它將無法擴展內存。
例如轉換為bd 文件 :
https://nycopendata.socrata.com/Social-Services/311-Service-Requests- from-2010-to-Present / erm2-nwe9
對於此數據庫文件SQL語言:
pd.read_sql_query("SELECT * FROM 'table'LIMIT 600000", Mydatabase)
使用PC的16 GB RAM內存,它最多可以讀取最多約0.6百萬條記錄(操作時間為15.8秒)。 添加直接從csv文件下載效率更高一點可能是惡意的:
giga_plik = 'c:/1/311_Service_Requests_from_2010_to_Present.csv'
Abdul = pd.read_csv(giga_plik, nrows=1100000)
(操作時間16,5秒)
第二個要點:為了有效地使用從CSV轉換的SQL數據系列,我們應該將適當的日期格式存儲到內存中。 因此,我的提議者將以下內容添加到ryguy72的代碼中:
df['ColumnWithQuasiDate'] = pd.to_datetime(df['Date'])
正如我指出的那樣,文件311的所有代碼:
start_time = time.time()
### sqlalchemy create_engine
plikcsv = 'c:/1/311_Service_Requests_from_2010_to_Present.csv'
WM_csv_datab7 = create_engine('sqlite:///C:/1/WM_csv_db77.db')
#----------------------------------------------------------------------
chunksize = 100000
i = 0
j = 1
## --------------------------------------------------------------------
for df in pd.read_csv(plikcsv, chunksize=chunksize, iterator=True, encoding='utf-8', low_memory=False):
df = df.rename(columns={c: c.replace(' ', '') for c in df.columns})
## -----------------------------------------------------------------------
df['CreatedDate'] = pd.to_datetime(df['CreatedDate']) # to datetimes
df['ClosedDate'] = pd.to_datetime(df['ClosedDate'])
## --------------------------------------------------------------------------
df.index += j
i+=1
df.to_sql('table', WM_csv_datab7, if_exists='append')
j = df.index[-1] + 1
print(time.time() - start_time)
最后,我想補充一點:將csv文件直接從Internet轉換為db在我看來是個壞主意。 我建議下載基礎並在本地轉換。
此代碼可以幫助您完成此任務。 它可瀏覽大型.csv文件,並且不會占用大量內存,因此您可以在標准筆記本電腦中執行此操作。
import pandas as pd
import os
chunksize2 = 2000
path = './'
data2 = pd.read_csv('ukb35190.csv',
chunksize=chunksize2,
encoding = "ISO-8859-1")
df2 = data2.get_chunk(chunksize2)
headers = list(df2.keys())
del data2
start_chunk = 0
data2 = pd.read_csv('ukb35190.csv',
chunksize=chunksize2,
encoding = "ISO-8859-1",
skiprows=chunksize2*start_chunk)
for i, df2 in enumerate(data2):
try:
print('reading cvs....')
print(df2)
print('header: ', list(df2.keys()))
print('our header: ', headers)
# Access chunks within data
# for chunk in data:
# You can now export all outcomes in new csv files
file_name = 'export_csv_' + str(start_chunk+i) + '.csv'
save_path = os.path.abspath(
os.path.join(
path, file_name
)
)
print('saving ...')
except Exception:
print('reach the end')
break
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.