1. 程式人生 > >Python:將大型CSV檔案轉化為DataFrame

Python:將大型CSV檔案轉化為DataFrame

    之前因為比賽一直在玩DataFrame,處理一些小型資料感覺很是方便。但是今天遇到了一個3.32G大的CSV檔案感覺甚是無力,總是報記憶體錯誤。上網查找了一些方法感覺都很有啟發啊,所以自己整合了一下。並記錄下來,以防記性不好的我忘記。

方法一:

with open('C:/Users/asus/Desktop/Python/test.csv') as f:
    for line in f:
        print line
這種方法雖然寫起來甚是簡便,程式碼量很少,但是讀出來的都是字串,不易清洗整理和計算,且耗時特別長,足有202s。但是可以一執行就出來東西,可以暫停來觀察內容的格式什麼的。

方法二:

def read_in_block(file_path):
    BLOCK_SIZE = 1024
    with open(file_path,'r') as f:
        while True:
            block = f.read(BLOCK_SIZE)  
            if block:
                yield block
            else:
                return # 若讀到檔案末尾,則退出

for block in read_in_block('C:/Users/asus/Desktop/Python/test.csv'):
    print block
方法二,寫了一個方法將路徑傳了進去,然後將檔案分成幾段進行讀取,每次讀取固定的長度到記憶體緩衝區,然後便釋放記憶體。耗時108s,比起第一種方法著實短了一半時間。但是相對於我這種剛入門的小白來說,面對如此龐大的字串資料仍是不好處理。我想要的是將它轉為DataFrame再進行處理。

方法三:

import pandas as pd
data = pd.read_csv('C:/Users/asus/Desktop/Python/test.csv',chunksize=1000000,header=None,sep=';')
for chunk in data:
    print chunk
玩方法三的時候著實讓我激動了一下,耗時57s!而且還轉換成了一個讓我感覺它就是DataFrame型別的資料。chunksize是pandas讀取csv檔案的方法其中一個小小的引數,一般使用read_csv()的時候,它都是為None的。但其實,當chunksize被設定為數值是,read_csv()就會迭代讀取資料,而不是一次性讀取。如此就會返回一個TextFileReader的迭代器,注意,是TextFileReader哦!!屬性是<class 'pandas.io.parsers.TextFileReader'>,而不是<class 'pandas.core.frame.DataFrame'>。是要用for迴圈才能取出資料的!否則就只能輸出<pandas.io.parsers.TextFileReader object at 0x03550530>。可憐我這小白,怪不得在我清洗資料的時候它總是報錯。然後我就想它for迴圈裡面的chunk是正宗的可以清洗的DataFrame啊,我就想著可以把這些chunk連線成一個新的DataFrame。於是:
data = pd.read_csv('C:/Users/asus/Desktop/Python/test.csv',chunksize=1000000,header=None,sep=';')
# print data
df = pd.DataFrame(columns=[0,1,2,3,4,5,6,7,8])    # 初始化一個空的DataFrame
for chunk in data:
    # print type(chunk)
    # print chunk
    df = pd.concat([df,chunk],ignore_index=True)    # 將chunk都連線起來形成一個DataFrame
print df
但是,它竟然又報我的記憶體錯誤!然後我想在連線之前先把一些資料清洗掉,於是我在for迴圈中又加了兩行程式碼:
for chunk in data:
    # print type(chunk)
    # print chunk
    chunk = chunk.dropna(axis=1)    # 去空
    chunk = chunk.drop_duplicates() # 刪除重複資料
    df = pd.concat([df,chunk],ignore_index=True)
print df

對於我的檔案,廢掉的資料有很多,所以我整理後資料縮減了很多,我覺得就是因為這樣我的程式才不會再報記憶體錯誤。由於這資料是指定的chunksize=1000000,即每100萬條資料讀取一次,分成了很多段,所以在整合一個新的DataFrame後,還需要再進行一些資料清洗整合去重什麼的。程式耗時68s。

方法四:

reader = pd.read_csv('C:/Users/asus/Desktop/Python/test.csv',iterator=True,sep=';')
loop = True
chunksize = 100000
chunks = []
while loop:
    try:
        chunk = reader.get_chunk(chunksize)
        chunk = chunk.dropna(axis=1)
        chunk = chunk.drop_duplicates()
        chunks.append(chunk)
    except StopIteration:
        loop = False
        print "Iteration is stopped."
df = pd.concat(chunks,ignore_index=True)
df = df.dropna(axis=1)
df = df.drop_duplicates()
print df
根據方法三的啟發,我又參考了這位大神的程式碼,又尋到了一種方法。也是分成了幾段,先清洗再整合串到一個DataFrame中,耗時50s。覺得這些大神的程式碼寫的真好,比我的好太多太多,真真是羨慕。自己需要加油去努力達到自己希望的高度吧。第一次寫部落格,有些佈局上面的失誤各位就不要深究了。在下一初玩Python的小白,有很多地方不懂,若有錯誤請多指點,但不要噴啊各位,我們要營造一個和諧友愛的網路環境啊參考連結:https://www.jianshu.com/p/f935673ef524
http://www.jb51.net/article/63603.htm