2012-11-21 23 views
3

我一直在尋找解決方案,但似乎無法找到任何東西。如何管理在R中生成大數據.tables? (不讀大表)

基本上我有一塊,我正在尋找擴展到大數據的代碼,代碼的樣本提取物是以下:

num_train <- 100 
num_test <- 100 

train <- data.table(k = rep(1,num_train), ID_train = 1:num_train, b_train = rnorm(num_train), c_train = rnorm(num_train), cat = sample(c("A", "B", "C", "D"), num_train, replace = TRUE)) 
test <- data.table(k = rep(1,num_test), ID_test = 1:num_test, b_test = rnorm(num_test), c_test = rnorm(num_test)) 

df <- merge(test,train, by="k") 

這將運行正是我希望它速度極快當我在更大的數據上使用它時。 (也許和num_train * num_test = 2,000,000,000 ...一樣大)

但是,問題在於生成的數據表是由num_train * num_test行增長的,所以很快R就無法處理。

num_train <- 1000 
num_test <- 10000 

train <- data.table(k = rep(1,num_train), ID_train = 1:num_train, b_train = rnorm(num_train), c_train = rnorm(num_train), cat = sample(c("A", "B", "C", "D"), num_train, replace = TRUE)) 
test <- data.table(k = rep(1,num_test), ID_test = 1:num_test, b_test = rnorm(num_test), c_test = rnorm(num_test)) 

df <- merge(test,train, by="k") 

>Error: cannot allocate vector of size 76.3 Mb 

我知道R的所有內存限制和包,如filehash,FF和bigmemory(不是太熟悉,已經使用了一些他們一點點的)。這些似乎允許您將大文件設置爲數據庫並有效地從中讀取數據。

但基本上我想知道的是,有沒有什麼辦法來管理創建從已經在內存中的表中的一個大表,就像它創建時將它的一部分寫入硬盤一樣?這些包中的任何一個都可以用於這個嗎?還有其他解決方案嗎?

或者這項工作只是不適用於R?

乾杯!

+0

弄清楚多少「塊」你可以不超載您的計算機的RAM存儲,然後在一次創建一個塊 - 其追加到FF,bigmemory,或者數據庫支持(SQL)表沒有佔用任何內存空間。然後刪除內存中的當前塊,然後轉到下一個塊。 –

+0

謝謝,這是我現在正在研究的一種方法。爲了我所做的工作,我可以用塊來處理它,但只能處理測試數據集。它需要應用於整個訓練數據集。因此,當訓練數據集大於10,000時,我需要將訓練數據集分成500個以下的行塊並循環,直到處理完所有內容......這種方式否定了data.tables包的速度。 – Ger

+0

好問題。同意安東尼。我做了一個快速計算:'2e9 * 9列* 8字節/ 1024^3 = 134 GB',所以是的,你正在研究你提到的軟件包。除非你可以找到一臺擁有那麼多內存的機器,或者一臺能夠在集羣或其他機器上分配你的內存的虛擬機。這是Revolution爲其提供(封閉源代碼)工具的領域。 –

回答

3

您可以使用軟件包ff和ffbase進行此操作。它不需要像data.table那樣將數據存入RAM中。 以下腳本將生成10Mio行x 10列data.frame。

num_train <- 1000 
num_test <- 10000 
train <- data.table(k = rep(1,num_train), ID_train = 1:num_train, b_train =  rnorm(num_train), c_train = rnorm(num_train), cat = sample(c("A", "B", "C", "D"), num_train,  replace = TRUE)) 
test <- data.table(k = rep(1,num_test), ID_test = 1:num_test, b_test = rnorm(num_test),  c_test = rnorm(num_test)) 


train <- data.frame(unclass(train), stringsAsFactors=TRUE) 
test <- data.frame(unclass(test), stringsAsFactors=TRUE) 
require(ffbase) 
train$id <- seq_len(nrow(train)) 
test$id <- seq_len(nrow(test)) 
train <- as.ffdf(data.frame(train, stringsAsFactors=TRUE)) 
test <- as.ffdf(data.frame(test, stringsAsFactors=TRUE)) 
x <- expand.ffgrid(train$id, test$id) 
dim(x) 
names(x) <- c("train.id", "test.id") 
x <- merge(x, train, by.x="train.id", by.y="id", all.x=TRUE, all.y=FALSE) 
x <- merge(x, test, by.x="test.id", by.y="id", all.x=TRUE, all.y=FALSE) 
dim(x) 
x[1:5, ] 
+0

謝謝,我喜歡這個解決方案,我不完全確定發生了什麼,但它似乎在您設置的示例中起作用。我想知道的唯一情況是這將如何按比例縮放(具體而言,expand.ffgrid()步驟對於10,000 * 10,000來說似乎相當緩慢)。這可以結合data.tables的速度嗎?看來我可以有一個很好的速度/差內存解決方案或低速/良好的內存... – Ger

+2

使用軟件包ff和ffbase是用於內存不足的解決方案。這意味着你的數據在磁盤上,並將在R中以塊的方式加載並再次放入磁盤。當然,RAM總是更快。如果您可以將所有數據存入RAM中,則不需要ff/ffbase。所以速度也取決於你的硬盤。所以與SQL或SAS的比較更適合。但爲了爭論的緣故,你可以做以下事情。 system.time(x < - 擴大。grid(as.ram(train $ id),as.ram(test $ id))) system.time(x < - as.ffdf(expand.grid(as.ram(train $ id),as.ram test $ id)))) system.time(x < - expand.ffgrid(train $ id,test $ id)) – jwijffels