簡體   English   中英

在python中順序讀取巨大的CSV文件

[英]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

這里的chunksize排序要在以后讀取的csv文件中的行數

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM