2013-12-11 60 views
1

在以下代碼中,「權重」是權重集的大矩陣。這個矩陣由1000行和4列組成。每行是一組權重(每行中元素的總和等於1)。 另外,還有四個對象,我想根據每個權重組選擇其中的一個。換句話說,這個隨機選擇應該重複所有的權重集。 現在我已經用for解決了這個問題。但是有沒有更有效的方法在R中進行編碼?在R中以不同概率重複採樣

y <- c("a", "b", "c", "d") 
for(i in 1:nrow(Weight)){ 
    selection[i] <- sample(y, 1, prob=Weight[i,]) #selection is a vector with the same number of rows as Weight 
} 
+0

你如何定義 「有效」? – flodel

回答

2

包裝你sample成一個功能,您可以只傳遞一個參數,從Weight行:

myfun <- function(w) { 
    sample(y, 1, prob=w) 
} 

然後你就可以使用申請家庭的一員:

apply(Weight, 1, myfun) 

但是,只要你預先分配了selection,你的方法並不是非常低效。

+0

或者,您可以直接使用'apply'而不創建額外的函數:'apply(Weight,1,sample,x = y,size = 1,replace = FALSE) –

5

更有效的方法是首先計算您的權重的按行累積和,然後在01之間繪製一個數字,然後查看它在哪個累積和中的位置。這樣,您只需要執行一個致電runif以獲取您的隨機數據,而使用其他方法致電1000致電。

Weight <- matrix(sample(1:100, 1000 * 4, TRUE), 1000, 4) 

x <- runif(nrow(Weight)) 
cumul.w <- Weight %*% upper.tri(diag(ncol(Weight)), diag = TRUE)/rowSums(Weight) 
i <- rowSums(x > cumul.w) + 1L 
selection <- y[i] 

還要注意我怎樣通過由三角矩陣相乘,而不是使用更慢apply(Weight, 1, cumsum)計算出的累計總和。一切都是矢量化的,所以它應該比使用applyfor循環更快。


applyfor基準比較:

f_runif <- function(Weight, y) { 
    x <- runif(nrow(Weight)) 
    cumul.w <- Weight %*% upper.tri(diag(ncol(Weight)), diag = TRUE)/
    rowSums(Weight) 
    i <- rowSums(x > cumul.w) + 1L 
    y[i] 
} 

f_for <- function(Weight, y) { 
    selection <- rep(NA, nrow(Weight)) 
    for(i in 1:nrow(Weight)){ 
    selection[i] <- sample(y, 1, prob=Weight[i,]) 
    } 
} 

f_apply <- function(Weight, y) { 
    apply(Weight, 1, function(w)sample(y, 1, prob=w)) 
} 

y <- c("a", "b", "c", "d") 
Weight <- matrix(sample(1:100, 1000 * 4, TRUE), 1000, 4) 

library(microbenchmark) 
microbenchmark(f_runif(Weight, y), 
       f_for (Weight, y), 
       f_apply(Weight, y)) 

# Unit: microseconds 
#    expr  min  lq median   uq  max neval 
# f_runif(Weight, y) 223.635 231.111 274.531 281.2165 1443.208 100 
# f_for(Weight, y) 10220.674 11238.660 11574.039 11917.1610 14583.028 100 
# f_apply(Weight, y) 9006.974 10016.747 10509.150 10879.9245 27060.189 100