2014-12-02 22 views
0

道歉的問題標題不佳。不太確定如何描述這裏的問題。
首先,我有下面的代碼。是否可以使用不同的向量應用於每列?

# Data 
set.seed(100) 
x = matrix(runif(10000,0,1),100,100) 
grpA = round(runif(100,1,5),0) # Group 1, 2, 3, 4, 5 

# function 
funA <-function(y, A){ 
    X = lm(y~A) 
    return(X$residuals) 
} 

# Calculation 
A = apply(x,1,function(y) funA(y,grpA)) 

現在,我沒有使用grpA,而是使用grpB,每個列的組數不同。除了循環每列之外,我還可以使用apply來計算它嗎?如果是這樣,怎麼樣?
我的實際樂趣計算要複雜得多,我需要多次計算funA,所以我試圖用for循環來避開。謝謝。

grpB = matrix(round(runif(10000,1,5),0),100,100) 

回答

0

只是作爲一個答案

我還可以使用該應用來計算呢?如果是這樣,怎麼樣?

答案是肯定的。您可以將xgrpB合併成一個array,然後在結果數組上應用apply。

# Data 
set.seed(100) 
x = matrix(runif(10000,0,1),100,100) 
grpA = round(runif(100,1,5),0) # Group 1, 2, 3, 4, 5 
# function 
funA <-function(y, A){ 
    X = lm(y~A) 
    return(X$residuals) 
} 
# Original calculation 
A <- apply(x, 1, funA, grpA) 
# the array in this case 
arr <- array(c(x, matrix(rep(grpA, 100), nrow=100, byrow=TRUE)), dim=c(nrow(x), ncol(x), 2)) 
# the new calculation 
res <- apply(arr, 1, function(y) funA(y[, 1], y[, 2])) 
# comparing results 
all.equal(A, res) 
## TRUE 
# 
# and for the new groupB 
grpB = matrix(round(runif(10000,1,5),0),100,100) 
# the array 
arr <- array(c(x, grpB), dim=c(nrow(x), ncol(x), 2)) 
# the calculation (same as above) 
res <- apply(arr, 1, function(y) funA(y[, 1], y[, 2])) 

查看@ mrip的答案,原因可能不是一個好主意。

0

你可以很容易使用的列數的sequence作爲「指標」或「提取」的變量,並使用vapply代替apply,像這樣:

vapply(sequence(ncol(x)), 
     function(z) funA(x[, z], grpB[, z]), 
     numeric(nrow(x))) 
4

首先,如果你的功能funA做了很多工作,然後使用for循環與apply不會對性能產生太大影響。這是因爲唯一的區別在於循環的開銷,並且在任何情況下,大部分工作都將在funA之內發生。

實際上,即使funA很簡單,forapply也不會在性能方面有所不同。無論哪種方式,都需要在R中使用多個R函數調用進行循環。通過避免for循環的實際性能改進來自於內置R函數,該函數通過在底層C代碼中循環而不需要R中多個函數調用的開銷來執行所需的計算。下面是一個說明性示例。

x<-matrix(runif(10000,0,1),100,100) 
require(microbenchmark) 
f1<-function(z){ 
    ret<-rep(0,ncol(z)) 
    for(i in 1:ncol(z)){ 
     ret[i]<-sum(z[,i]) 
    } 
    ret 
} 
f2<-function(z){ 
    apply(z,2,sum) 
} 
identical(f1(x),f2(x)) 
# [1] TRUE 
identical(f1(x),colSums(x)) 
# [1] TRUE 
microbenchmark(f1(x),f2(x),colSums(x)) 
# unit: microseconds 
#  expr  min  lq median  uq  max neval 
#  f1(x) 559.934 581.4775 596.4645 622.1425 773.519 100 
#  f2(x) 484.265 512.1570 526.5700 546.5010 1100.540 100 
# colSums(x) 23.844 25.7915 27.0675 28.7575 59.485 100 

因此,在你的情況下,我不會擔心使用for循環。有一些方法可以避免循環,例如,類似於

sapply(1:ncol(x),function(i) fun(x[,i],y[,i])) 

但它不會比for循環快得多。

+0

沒錯。可以使用'lm(t(x)〜groupA)'來避免R級的循環。如果需要循環,也可以使用'lm.fit'。課程:如果可能,避免使用R循環。如果不優化循環內的代碼。 – Roland 2014-12-02 15:38:19

相關問題