2012-12-28 38 views
1

我有一個數據框,它由第一列(experiment.id)組成,其餘列是與此實驗ID相關的值。每一行都是唯一的實驗ID。我的數據框的列數爲10 4 - 10 5。高效採樣數據幀避免循環

data.frame(experiment.id=1:100, v1=rnorm(100,1,2),v2=rnorm(100,-1,2)) 

該數據框是我的樣本空間的來源。我想要做的是爲每個獨特的實驗.id(行)隨機抽樣(與替換)與此id相關聯的值v1,v2,...,v10000中的一個,並構造一個樣本s1。在每個樣本s1中,代表所有實驗ID。

最終我想執行10 4個樣本,s1,s2,...,s 10 4並計算一些統計量。

什麼是最有效的方法(計算)來執行此採樣過程。我想盡可能避免循環。

更新: 我的問題不是全部關於採樣,而是存儲樣本。我想我真正的問題是,如果有比

d<-data.frame(experiment.id=1:1000, replicate (10000,rnorm(1000,100,2))) 
results<-data.frame(d$experiment.id,replicate(n=10000,apply(d[,2:10001],1,function(x){sample(x,size=1,replace=T)}))) 
+0

實驗。id是任何唯一的字符串/數 – ECII

+1

'replicate'和'apply'本質上是循環和緩慢的。如果您有能力存儲這樣的矩陣,那麼到目前爲止發佈的任何答案都會更快。如果空間確實成爲問題,那麼您需要遍歷行並在您離開時從中獲取統計數據。所以,提前瞭解這一部分。到目前爲止,你已經暗示你需要1e9的值。這正在進入一個多千兆字節的矩陣。 – John

+0

@John感謝您的輸入。正如你所提到的,我的主要問題是計算時間和存儲量,而不是抽樣程序本身。 「即時」計算統計數據可以提供一個選項,但事先提供完整的數據集並進行事後分析會很方便。感謝您的輸入。 – ECII

回答

2

最短和最可讀恕我直言,仍然使用apply,而是充分利用的事實,sample被矢量:

results <- data.frame(experiment.id = d$experiment.id, 
         t(apply(d[, -1], 1, sample, 10000, replace = TRUE))) 

如果3秒時需要有適合您的需求太慢那我就建議您使用矩陣索引。

+0

這是正確的嗎?您對每一行進行採樣並返回一個向量。該向量如何輸入結果數據框? – ECII

+0

這個速度將取決於行數 – John

+0

@ECII,'t(apply(...))'將返回一個1000×10000的矩陣,這個矩陣將被數據綁定到實驗ID上。 frame'。試一試。 – flodel

3

這裏執行上述以外的更快捷的方法是,選擇的列(不包括第一次)的一個表達。它不會複製第一列,您需要將其作爲單獨的步驟提供。

對於數據幀d

d[matrix(c(seq(nrow(d)), sample(ncol(d)-1, nrow(d), replace=TRUE)+1), ncol=2)] 

這是一個樣本。爲了得到N樣品,只是乘的選擇(如在約翰的回答):

mm <- matrix(c(rep(seq(nrow(d)), N), sample(ncol(d)-1, nrow(d)*N, replace=TRUE)+1), ncol=2) 

result <- matrix(d[mm], ncol=N) 

但你將有內存問題。

+0

謝謝。你的第一行構建一個樣本。然而,我想要構建*並存儲* 10 4個樣本,然後進行一些統計。創建和存儲大量樣本會有效嗎? – ECII

+0

@ECII將它保存爲變量?否則,我不確定你在問什麼。 –

+0

將所有樣本保存到數據框以進行進一步的統計分析。看到我的問題和約翰的評論更新 – ECII

2

這是可能的,沒有任何循環。如果將第一個列之後的列轉換爲矩陣,這很容易實現,因爲矩陣可以按[行,列]或按順序排列,因爲它是基礎向量。

mat <- as.matrix(datf[,-1]) 
nr <- nrow(mat); nc <- ncol(mat) 
sel <- sample(1:nc, nr, replace = TRUE) 
sel <- sel + ((1:nr)-1) * nc 
x <- t(mat)[sel] 
seldatf <- data.frame(datf[,1], x = x) 

現在,要獲得大量的樣本,只需乘以相同的邏輯即可。

ns <- 10 # number of samples/row 
sel <- sample(1:nc, nr * ns, replace = TRUE) 
sel <- sel + rep(((1:nr)-1) * nc, each = ns) 
x <- t(mat)[sel] 
seldatf <- cbind(datf[,1], data.frame(matrix(x, ncol = ns, byrow = TRUE))) 

這是可能的,這將是一個非常大的數據幀,如果你要設置ns <- 1e5,你有大量的行。你可能不得不注意內存不足。出於可讀性原因,我會進行一些不必要的複製。你可以消除內存和速度,因爲一旦你使用大量的內存,你將會換出其他正在運行的程序。這很慢。您不必分配和保存x,mat,甚至是sel。不這樣做的結果會爲您提供儘可能快的答案。