Вот подход «применять / применять» со сравнениями с более наивным циклическим подходом.Ускорение примерно в 3 раза (хотя зависит от процента негативов в матрице).Если цикл, который вы выполняете, еще более наивен (например, без предварительного распределения), то ускорение будет больше, но в этом случае проблема действительно в цикле как таковом, а не в отсутствии фильтрации каждой строки.Наилучший подход - это написать полностью векторизованный код, если это вообще возможно, и пропустить циклы или полностью выполнить.Без подробностей невозможно сказать, что бы это значило в вашем случае.Я добавил, что для сравнения будет работать полностью векторизованная версия, использующая rowSums()
.Как вы можете видеть, вот где реальное ускорение:
#functions to create a vector of sums where f is applied to the rows of A
#The first method is a naive loop, the second takes advantage of the fact that
#x < 0 imples f(x) == 0
method1 <- function(A,f){
m <- nrow(A)
n <- ncol(A)
v <- rep(0,m)
for(i in 1:m){
row <- rep(0,n)
for(j in 1:n){
row[j] = f(A[i,j])
}
v[i] = sum(row)
}
v
}
method2 <- function(A,f){
apply(A,1,function(row){sum(sapply(row[row >= 0],f))})
}
#for testing:
f <- function(x) max(0,x)^2
g <- function(x) pmax(x,0)^2 #vectorized version of f
A <- matrix(runif(10000,-10,2),nrow = 100)
library(microbenchmark)
print(microbenchmark(method1(A,f),method2(A,f),rowSums(g(A))))
Типичный вывод (на моей машине):
Unit: microseconds
expr min lq mean median uq max neval
method1(A, f) 13826.824 14672.9285 16076.5778 15342.0195 16916.631 33829.384 100
method2(A, f) 5629.886 6009.6550 6687.8325 6247.3185 7117.401 14411.815 100
rowSums(g(A)) 217.566 249.6535 315.7482 271.8685 303.075 2918.966 100