python大規模數據處理技巧之一:數據常用操作


面對讀取上G的數據,python不能像做簡單代碼驗證那樣隨意,必須考慮到相應的代碼的實現形式將對效率的影響。如下所示,對pandas對象的行計數實現方式不同,運行的效率差別非常大。雖然時間看起來都微不足道,但一旦運行次數達到百萬級別時,其運行時間就根本不可能忽略不計了:

 

 

故接下來的幾個文章將會整理下渣渣在關於在大規模數據實踐上遇到的一些問題,文章中總結的技巧基本是基於pandas,有錯誤之處望指正。

1、外部csv文件讀寫
大數據量csv讀入到內存
分析思路:數據量非常大時,比如一份銀行一個月的流水賬單,可能有高達幾千萬的record。對於一般性能的計算機,有或者是讀入到特殊的數據結構中,內存的存儲可能就非常吃力了。考慮到我們使用數據的實際情況,並不需要將所有的數據提取出內存。當然讀入數據庫是件比較明智的做法。若不用數據庫呢?可將大文件拆分成小塊按塊讀入后,這樣可減少內存的存儲與計算資源
注意事項:open(file.csv)與pandas包的pd.read_csv(file.csv ): python32位的話會限制內存,提示太大的數據導致內存錯誤。解決方法是裝python64位。如果嫌python各種包安裝過程麻煩,可以直接安裝Anaconda2 64位版本
簡易使用方法:
chunker = pd.read_csv(PATH_LOAD, chunksize = CHUNK_SIZE)
讀取需要的列:
columns = ("date_time", "user_id")
chunks_train = pd.read_csv(filename, usecols = columns, chunksize = 100000)


chunker對象指向了多個分塊對象,但並沒有將實際數據先讀入,而是在提取數據時才將數據提取進來。數據的處理和清洗經常使用分塊的方式處理,這能大大降低內存的使用量,但相比會更耗時一些

分塊讀取chunk中的每一行:
for rawPiece in chunker_rawData:
current_chunk_size = len(rawPiece.index) #rawPiece 是dataframe
for i in range(current_chunk_size ):
timeFlag = timeShape(rawPiece.ix[i]) #獲取第i行的數據
將數據存到硬盤
直接寫出到磁盤:
data.to_csv(path_save, index = False, mode = 'w')`
分塊寫出到磁盤:
對於第一個分塊使用pandas包的存儲IO:
保留header信息,‘w’模式寫入
data.to_csv(path_save, index = False, mode = 'w')
接下的分塊寫入
去除header信息,‘a’模式寫入,即不刪除原文檔,接着原文檔后繼續寫
data.to_csv(path_save, index = False, header = False, mode = a')
少量的數據寫出:
少量的數據用pickle(cPickle更快)輸出和讀取,非常方便 ,下面分別是寫出和讀入

寫出:

import cPickle as pickle
def save_trainingSet(fileLoc, X, y):
pack = [X, y]
with open(fileLoc, 'w') as f:
pickle.dump(pack, f)

讀入:

import cPickle as pickle
def read_trainingSet(fileLoc):
with open(fileLoc, 'r') as f:
pack = pickle.load(f)
return pack[0], pack[1]

高效讀取外部csv到python內部的list數據結構
效率低下的方法:使用pd讀入需要從pd轉換到python本身的數據結構,多此一舉
userList = []
content = pd.read_csv(filename)
for i in range(len(content)):
line = content.ix[i]['id']
userList.append(line)

效率高的方法:直接將外部數據讀入進來
userList = []
f = open(filename)
content = f.readlines()
for line in content:
line = line.replace('\n', '').split(',')
userList.append(line)

2、數據分析時常用數據結構之間的轉化
數據集的橫向與縱向合並
簡單地橫向合並數據集:
問題分析:
縱向的合並使用list並不好,因為需要去拆解list的每一個行元素,並用extend去拓展每一行的縱向元素
最好使用dataframe中的concat函數:c = pd.concat([a, b], axis = 1),當axis=0時表示合並行(以行為軸)
inx1 = DataFrame(np.random.randn(nSample_neg), columns = ['randVal'])
inx2 = DataFrame(range(nSample_neg), columns = ['inxVal'])
inx = pd.concat([inx1, inx2], axis = 1)

類似數據庫的表合並:join(待完整)
ret = ret.join(dest_small, on="srch_destination_id", how='left', rsuffix="dest")

簡單縱向合並數據集:
縱向合並數據集可以考慮一下幾種方法:
讀取數據為list格式,使用append函數逐行讀取
將數據集轉換為pandas中的dataframe格式,使用dataframe的merge與concat方法
方法:
方法一:使用dataframe讀入,使用concat把每行並起來
方法二:先使用list讀入並起來,最后轉換成dataframe
方法三:先使用list讀入並起來大塊的list,每塊list轉換成dataframe后用concat合並起來
比較:方法一由於concat的靜態性,每次要重新分配資源,故跑起來很慢; 方法二與三:會快很多,但具體沒有測試,以下是使用方法三的代碼:
data = []
cleanedPiece = []
for i in range(CHUNK_SIZE):
line = rawPiece.ix[i]
uid = [line['user_id'], line['item_id'],
line['behavior_type'], timeFlag]
cleanedPiece.append(uid)
cleanedPiece = DataFrame(cleanedPiece, columns = columns)
data = pd.concat([data, cleanedPiece], axis = 0)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM