Mat*_*ice 9 performance matlab r
我在R和MATLAB上使用多维数组,这些数组有五个维度(总共14.5M的元素).我必须删除一个应用算术平均值的维度,我发现使用这两个软件的性能差异很大.
MATLAB:
>> a = rand([144 73 10 6 23]);
>> tic; b = mean(a,3); toc
Elapsed time is 0.014454 seconds.
Run Code Online (Sandbox Code Playgroud)
R:
> a = array(data = runif(144*73*6*23*10), dim = c(144,73,10,6,23))
> start <- Sys.time (); b = apply(a, c(1,2,4,5), mean); Sys.time () - start
Time difference of 1.229083 mins
Run Code Online (Sandbox Code Playgroud)
我知道应用函数很慢,因为它类似于通用函数,但我不知道如何处理这个问题,因为这种性能差异对我来说真的是一个很大的限制.我试图搜索colMeans/rowMeans函数的泛化,但我没有成功.
编辑 我将展示一个小样本矩阵:
> dim(a)
[1] 2 4 3
> dput(aa)
structure(c(7, 8, 5, 8, 10, 11, 9, 9, 6, 12, 9, 10, 12, 10, 14,
12, 7, 9, 8, 10, 10, 9, 8, 6), .Dim = c(2L, 4L, 3L))
a_mean = apply(a, c(2,3), mean)
> a_mean
[,1] [,2] [,3]
[1,] 7.5 9.0 8.0
[2,] 6.5 9.5 9.0
[3,] 10.5 11.0 9.5
[4,] 9.0 13.0 7.0
Run Code Online (Sandbox Code Playgroud)
编辑(2):
我发现应用sum函数然后除以删除的维度的大小肯定更快:
> start <- Sys.time (); aaout = apply(aa, c(1,2,4,5), sum); Sys.time () - start
Time difference of 5.528063 secs
Run Code Online (Sandbox Code Playgroud)
flo*_*del 22
在R中,apply
不是适合该任务的工具.如果你有一个矩阵并需要行或列的意思,你会使用更快,矢量化rowMeans
和colMeans
.您仍然可以将它们用于多维数组,但您需要有点创意:
假设您的数组具有n
维度,并且您想要计算沿维度的平均值i
:
aperm
将尺寸移动i
到最后位置n
rowMeans
与dims = n - 1
同样,您可以:
aperm
将尺寸移动i
到第一个位置colMeans
与dims = 1
a <- array(data = runif(144*73*6*23*10), dim = c(144,73,10,6,23))
means.along <- function(a, i) {
n <- length(dim(a))
b <- aperm(a, c(seq_len(n)[-i], i))
rowMeans(b, dims = n - 1)
}
system.time(z1 <- apply(a, c(1,2,4,5), mean))
# user system elapsed
# 25.132 0.109 25.239
system.time(z2 <- means.along(a, 3))
# user system elapsed
# 0.283 0.007 0.289
identical(z1, z2)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)
mean
由于S3方法调度,特别慢.这更快:
set.seed(42)
a = array(data = runif(144*73*6*23*10), dim = c(144,73,10,6,23))
system.time({b = apply(a, c(1,2,4,5), mean.default)})
# user system elapsed
#16.80 0.03 16.94
Run Code Online (Sandbox Code Playgroud)
如果您不需要处理NA
s,则可以使用内部函数:
system.time({b1 = apply(a, c(1,2,4,5), function(x) .Internal(mean(x)))})
# user system elapsed
# 6.80 0.04 6.86
Run Code Online (Sandbox Code Playgroud)
为了比较:
system.time({b2 = apply(a, c(1,2,4,5), function(x) sum(x)/length(x))})
# user system elapsed
# 9.05 0.01 9.08
system.time({b3 = apply(a, c(1,2,4,5), sum)
b3 = b3/dim(a)[[3]]})
# user system elapsed
# 7.44 0.03 7.47
Run Code Online (Sandbox Code Playgroud)
(请注意,所有时间只是近似的.适当的基准测试需要代表性地运行,例如,使用其中一个bechmarking包.但我现在对此没有足够的耐心.)
有可能通过Rcpp实现加快速度.