本文翻譯自R in Action的附錄G,如果對該書感興趣,請自行購買或去圖書館閱讀。
R會把所有的對象讀存入虛擬內(nèi)存中。對我們大多數(shù)用戶來說,這種設(shè)計可以提高與R相互的速度,但是當(dāng)分析大數(shù)據(jù)集時,這種設(shè)計會降低程序運行速度有時還會產(chǎn)生跟內(nèi)存相關(guān)的錯誤。
內(nèi)存限制主要取決于R的build版(32位還是64位),而在32位的windows下,取決于操作系統(tǒng)的版本。以cannot allocate vectoe of size開頭的出錯信息表示無法分配充足的連續(xù)內(nèi)存,而以cannot allocate vector of length開頭的出錯信息表示超越了地址限制(address limit)。在處理大數(shù)據(jù)集時,應(yīng)盡量使用64位版的R。對于各種build版,向量中的元素個數(shù)最大為2147483647(請自行?Memory)。
在處理大數(shù)據(jù)集時有三方面應(yīng)該考慮:(a)提高程序的效率,保證執(zhí)行速度;(b)把數(shù)據(jù)儲存在外部,以解決內(nèi)存限制問題;(c)使用專門的統(tǒng)計方法來有效處理大數(shù)據(jù)量的問題。
下面將分別討論。
高效編程下面幾條編程技巧來可以提高處理大數(shù)據(jù)集時的效率
- 盡量向量化運算。使用R內(nèi)置的函數(shù)來處理向量、矩陣和list(例如函數(shù)sapply,lapply和mapply),盡量避免使用循環(huán)(for和while);
- 使用矩陣,必要時才使用數(shù)據(jù)框,因為矩陣的開銷更少;
- 使用read.table()函數(shù)族把外部數(shù)據(jù)導(dǎo)入數(shù)據(jù)框時,盡量顯式設(shè)定colClasses和nrows選項,設(shè)定comment.char = "",把不需要的列設(shè)置成NULL。這樣可以減少占用的內(nèi)存,同時加快處理速度。將外部數(shù)據(jù)導(dǎo)入矩陣時,使用scan()函數(shù);
- 在處理全部數(shù)據(jù)前,用數(shù)據(jù)的子集測試程序,來優(yōu)化程序,去掉bug;
- 刪除臨時對象和不再用的對象。調(diào)用rm(list=ls())可以刪除內(nèi)存中的所有對象。刪除指定的對象可以用rm(object);
- 在Jeromy Anglim的博客文章“R的內(nèi)存管理:一些小竅門和技巧”(原文Memory Management in R: A Few Tips and Tricks,被墻)中提到,使用函數(shù).ls.objects()列出工作區(qū)內(nèi)的對象占用的內(nèi)存大小。這個函數(shù)會幫助你找到吃內(nèi)存的大家伙。
- profile你的程序,看看在每個函數(shù)中花的時間。你可以用Rprof()和summaryRprof()函數(shù)完成這項工作。system.time()函數(shù)也可以幫助你。profr 和 prooftools 包提供了若干函數(shù)來幫助分析profile的輸出。
- Rcpp包可以把R對象轉(zhuǎn)成C++函數(shù)(原文是The Rcpp package can be used to transfer R objects to C++ functions and back when more optimized subroutines are needed. 后半句不知怎么翻譯)
處理大數(shù)據(jù)集,提高代碼效率只能解決一部分問題。你也可以把數(shù)據(jù)存在外部存儲并使用專門的統(tǒng)計分析方法。
把數(shù)據(jù)存儲在內(nèi)存之外有幾種包可以實現(xiàn)在內(nèi)存之外存儲數(shù)據(jù)。解決之道是把數(shù)據(jù)保存在外部數(shù)據(jù)庫或者硬盤里的二進制文件中,然后在需要的時候部分地讀取。下表描述了幾種有用的包:
包 | 描述 |
ff | 提供了一種數(shù)據(jù)結(jié)構(gòu),保存在硬盤中,但是操作起來就如同在內(nèi)存中一樣 |
bigmemory | 支持大規(guī)模矩陣的創(chuàng)建、儲存、讀取和操作。矩陣被分配到共享內(nèi)存或內(nèi)存映射的文件中(memory-mapped files) |
filehash | 實現(xiàn)了簡單的key-value數(shù)據(jù)庫,在其中特征字符串key與存儲在硬盤中的數(shù)據(jù)value相關(guān)聯(lián)。 |
ncdf, ncdf4 | Provides an interface to Unidata netCDF data files. |
RODBC, RMySQL, ROracle, RPostgreSQL, RSQLite | 可以用這些包讀取外部關(guān)系數(shù)據(jù)庫管理系統(tǒng)的數(shù)據(jù) |
上面的包可以幫助客服R的內(nèi)存限制。除此以外,當(dāng)需要在有限時間內(nèi)分析大數(shù)據(jù)集時,使用專門方法也是必須的。一些有用的方法將在下面介紹。
分析大數(shù)據(jù)集的包R提供了幾種分析大數(shù)據(jù)集的包:
- biglm 和 speedglm 包可以針對大數(shù)據(jù)集有效地擬合線性和廣義線性模型。在處理大規(guī)模數(shù)據(jù)集時,這兩個包提供了類似lm()和glm()的功能。
- 由 bigmemory 包可產(chǎn)生大規(guī)模矩陣,一些包可以提供分析這些大規(guī)模矩陣的函數(shù)。bigannalytics 包提供了k-means聚類、行統(tǒng)計量(column statistics)和一個對biglm()的封裝。bigtabulate 包提供了table()、split()和tapply()的功能,bigalgebra 包提供了高等線性代數(shù)的函數(shù)。
- biglars 包提供了最小角回歸(least-angle regression)、lasso以及針對大數(shù)據(jù)集的逐步回歸,數(shù)據(jù)集因太大而不能讀入到內(nèi)存中,這時候要配合 ff 包使用。
- Brobdingnag 包可以用來處理大數(shù)字(大于2^1024)
處理從GB到TB級的數(shù)據(jù)對于任何數(shù)據(jù)都是極大的挑戰(zhàn)。如果想查看R的更多方法,請看CRAN task View: High-Performance and Parallel Computing with R(http://cran./web/views/HighPerformanceComputing.html)。