是否可以使用不同的向量应用于每列?

是否可以使用不同的向量应用于每列?

问题描述:

道歉的问题标题不佳。不太确定如何描述这里的问题。
首先,我有下面的代码。是否可以使用不同的向量应用于每列?

# 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) 

只是作为一个答案

我还可以使用该应用来计算呢?如果是这样,怎么样?

答案是肯定的。您可以将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的答案,原因可能不是一个好主意。

你可以很容易使用的列数的sequence作为“指标”或“提取”的变量,并使用vapply代替apply,像这样:

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

首先,如果你的功能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