如何将函数应用于R中matrix(或dataframe)的每一行
假设我有一个2×2的matrix和一个把2个vector作为它的一个参数的函数。 我想将这个函数应用到matrix的每一行,并得到一个n向量。 如何在R中做到这一点?
例如,我想计算三点的2D标准正态分布的密度:
bivariate.density(x=c(0,0),mu=c(0,0), sigma=c(1,1), rho=0){ exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+x[2]^2/sigma[2]^2-2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2)) } out=rbind(c(1,2),c(3,4),c(5,6));
如何将函数应用到每一行?
如何通过指定的方式将除了点之外的其他参数的值传递给函数?
谢谢!
你只需使用apply()
函数:
R> M <- matrix(1:6, nrow=3, byrow=TRUE) R> M [,1] [,2] [1,] 1 2 [2,] 3 4 [3,] 5 6 R> apply(M, 1, function(x) 2*x[1]+x[2]) [1] 4 10 16 R>
这需要一个matrix,并应用(愚蠢)函数到每一行。 您将额外的参数作为第四,第五,…parameter passing给apply()
。
如果你想应用常见的函数,如sum或mean,你应该使用rowSums
或rowMeans
因为它们比apply(data, 1, sum)
方法快。 否则,坚持apply(data, 1, fun)
。 您可以在FUN参数后传递额外的参数(如Dirk已经提示的那样):
set.seed(1) m <- matrix(round(runif(20, 1, 5)), ncol=4) diag(m) <- NA m [,1] [,2] [,3] [,4] [1,] NA 5 2 3 [2,] 2 NA 2 4 [3,] 3 4 NA 5 [4,] 5 4 3 NA [5,] 2 1 4 4
那么你可以做这样的事情:
apply(m, 1, quantile, probs=c(.25,.5, .75), na.rm=TRUE) [,1] [,2] [,3] [,4] [,5] 25% 2.5 2 3.5 3.5 1.75 50% 3.0 2 4.0 4.0 3.00 75% 4.0 3 4.5 4.5 4.00
这是一个应用函数到matrix的每一行的简单例子。 (这里,应用的函数将每行标准化为1)
注意: apply()
的结果必须使用t()
进行转置,以获得与inputmatrixA
相同的布局。
A <- matrix(c( 0, 1, 1, 2, 0, 0, 1, 3, 0, 0, 1, 3 ), nrow = 3, byrow = TRUE) t(apply(A, 1, function(x) x / sum(x) ))
结果:
[,1] [,2] [,3] [,4] [1,] 0 0.25 0.25 0.50 [2,] 0 0.00 0.25 0.75 [3,] 0 0.00 0.25 0.75
第一步是制作function对象,然后应用它。 如果你想要一个具有相同行数的matrix对象,你可以预先定义它,并使用对象[]forms(否则返回值将被简化为一个向量):
bvnormdens <- function(x=c(0,0),mu=c(0,0), sigma=c(1,1), rho=0){ exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+ x[2]^2/sigma[2]^2- 2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2)) } out=rbind(c(1,2),c(3,4),c(5,6)); bvout<-matrix(NA, ncol=1, nrow=3) bvout[] <-apply(out, 1, bvnormdens) bvout [,1] [1,] 1.306423e-02 [2,] 5.931153e-07 [3,] 9.033134e-15
如果你想使用非默认的参数,那么调用应该在函数后面包含命名参数:
bvout[] <-apply(out, 1, FUN=bvnormdens, mu=c(-1,1), rho=0.6)
apply()也可以用在高维数组上,MARGIN参数可以是一个向量,也可以是一个整数。
另一种方法,如果你想使用数据集的不同部分,而不是一个单一的价值是使用rollapply(data, width, FUN, ...)
。 使用宽度vector可以在数据集的不同窗口上应用函数。 我用它来构build一个自适应过滤例程,虽然效率不高。
应用做得好,但是速度很慢。 使用sapply和vapply可能是有用的。 dplyr的rowwise也可能是有用的让我们看一个如何做任何数据框的行明智的产品的例子。
a = data.frame(t(iris[1:10,1:3])) vapply(a, prod, 0) sapply(a, prod)
请注意,在使用vapply / sapply / apply之前分配给variables是一个很好的做法,因为它可以减less很多时间。 让我们看看microbenchmark结果
a = data.frame(t(iris[1:10,1:3])) b = iris[1:10,1:3] microbenchmark::microbenchmark( apply(b, 1 , prod), vapply(a, prod, 0), sapply(a, prod) , apply(iris[1:10,1:3], 1 , prod), vapply(data.frame(t(iris[1:10,1:3])), prod, 0), sapply(data.frame(t(iris[1:10,1:3])), prod) , b %>% rowwise() %>% summarise(p = prod(Sepal.Length,Sepal.Width,Petal.Length)) )
仔细看看如何使用t()