我经常需要将函数应用于数据框/矩阵中的每对列,并以矩阵形式返回结果.现在我总是写一个循环来做这件事.例如,要创建一个包含相关p值的矩阵,我写道:
df <- data.frame(x=rnorm(100),y=rnorm(100),z=rnorm(100))
n <- ncol(df)
foo <- matrix(0,n,n)
for ( i in 1:n)
{
for (j in i:n)
{
foo[i,j] <- cor.test(df[,i],df[,j])$p.value
}
}
foo[lower.tri(foo)] <- t(foo)[lower.tri(foo)]
foo
[,1] [,2] [,3]
[1,] 0.0000000 0.7215071 0.5651266
[2,] 0.7215071 0.0000000 0.9019746
[3,] 0.5651266 0.9019746 0.0000000
Run Code Online (Sandbox Code Playgroud)
哪个有效,但对于非常大的矩阵来说非常慢.我可以在R中为此编写一个函数(通过假设如上所述的对称结果,不会因为切割时间减半而烦恼):
Papply <- function(x,fun)
{
n <- ncol(x)
foo <- matrix(0,n,n)
for ( i in 1:n)
{
for (j in 1:n)
{
foo[i,j] <- fun(x[,i],x[,j])
}
}
return(foo)
}
Run Code Online (Sandbox Code Playgroud)
或者是Rcpp的函数:
library("Rcpp")
library("inline")
src <-
' …Run Code Online (Sandbox Code Playgroud) 标准R表达式outer(X, Y, f)求值为矩阵,其第(i,j)个条目具有该值f(X[i], Y[j]).
我想实现这个函数multi.outer,一个n维泛化outer:multi.outer(f, X_1, ..., X_n),其中f是一些n元函数,会产生一个(长度(X_1)*...*长度(X_n))数组,其中(i_1,... .,i_n)-th entry具有f(X_1[i_1], ..., X_n[i_n])所有有效索引集(i_1,...,i_n)的值.显然,对于每个i在{1,...,N},的所有元素X_i中multi.outer(f, X_1,...,X_i,..., X_n)必须是可允许的第i个参数的函数f.对于n = 2的情况,multi.outer会做同样的事情outer,虽然它会有不同的签名(IOW,multi.outer(f, X, Y)相当于outer(X, Y, f)).
重要的是要注意,尽管参数X_1,...,X_n multi.outer都是向量,但它们不一定都具有相同的模式.例如,X_1和X_2可以分别为c(1, 2, 3)和LETTERS[10:20].
谢谢!