我想获取data.frame / matrix的列并在数据帧的每个单元格([i, j]
)之间应用函数,其中i和j是data.frame列的序列。基本上我想填充单个单元格的矩阵,就像cor
函数与data.frame一样。
这是一个相关的问题:Create a matrix from a function and two numeric data frames但是,我在随机化测试中使用它并多次重复操作(制作许多矩阵)。我正在寻找最快的方法来完成这项操作。我使用并行处理加快了一些事情,但我对这个速度仍然不满意。不能假设矩阵输出也是对称的,即cor
产生对称矩阵的方式(我的例子将反映这一点)。
我今天在data.table网页上看到了http://datatable.r-forge.r-project.org/)以下内容:
比
快500倍以上DF[i,j]<-value
这让我想到,或许data.table
或dplyr
或其他方式可能会加速一些事情。我的大脑已被固定在填充细胞上,但也许有更好的方法涉及重塑,应用函数并重新整形为矩阵或沿着这些线的东西。我可以使用outer
或for
循环在基本R中实现此目的,如下所示。
## Arbitrary function
FUN <- function(x, y) round(sqrt(sum(x)) - sum(y), digits=1)
## outer approach
outer(
names(mtcars),
names(mtcars),
Vectorize(function(i,j) FUN(mtcars[,i],mtcars[,j]))
)
## for approach
mat <- matrix(rep(NA, ncol(mtcars)^2), ncol(mtcars))
for (i in 1:ncol(mtcars)) {
for (j in 1:ncol(mtcars)) {
mat[i, j] <- FUN(mtcars[, i], mtcars[, j])
}
}
mat
以下microbenchmark时间安排for
略有优势。
Unit: milliseconds
expr min lq median uq max neval
OUTER() 4.450410 4.691124 4.774394 4.877724 55.77333 1000
FOR() 4.309527 4.521785 4.588728 4.694156 7.04275 1000
R中最快的方法是什么(欢迎加入套餐)?
答案 0 :(得分:3)
仍然坚持base
R解决方案,我在基于for
的方法中获得了1.6-1.7倍的加速:
[,i]
代替[[i]]
(显着的时间影响 - 也许FUN
只接收C指针而不是新分配的向量); FUN
的字节码编译(小时间影响); for
代码包装到函数+字节代码编译(小时间影响); 代码:
library(compiler)
FUN2 <- cmpfun(FUN)
for2 <- cmpfun(function(mtcars, FUN) {
mat <- matrix(rep(NA, ncol(mtcars)^2), ncol(mtcars))
for (i in 1:ncol(mtcars)) {
for (j in 1:ncol(mtcars)) {
mat[i, j] <- FUN(mtcars[[i]], mtcars[[j]])
}
}
mat
})
基准:
Unit: milliseconds
min lq median uq max neval
outer 7.791739 7.991474 8.245869 8.538163 16.24460 100
for 8.143679 8.463249 8.588230 9.912008 16.30842 100
for-mods 4.713837 4.875972 5.006202 5.246584 15.66491 100
在我看来,很难找到更快的方法(但我可能错了)。与多次计算for
所需的时间相比,FUN
循环时间偏差非常小(约0.25 ms)。