- Петли являются простыми и не обязательно медленными.Однако это зависит от того, как использовать эти циклы.Например, в вашем коде (я называю ваш подход
L.GUEGAN()
, для дальнейшей справки) вы не используете тот факт, что знаете размер вашей конечной сетки и продолжаете расширять векторы, матрицы.Это замедляет ход событий.Очень простой альтернативой будет
niceFor <- function() {
grid <- matrix(0, nrow = length(inputVector1), ncol = length(inputVector2))
for(i in seq_along(inputVector1))
for(j in seq_along(inputVector2))
grid[i, j] <- i + j
grid
}
, где существенным отличием является предварительное определение объекта сетки и обновление его значений, а не создание новых объектов.
Да, вы можете сказать, что есть специальная функция для чего:
outer(inputVector1, inputVector2, `+`)
Однако необходимо помнить, что функция в третьем аргументенеобходимо векторизовать, что имеет место в этой ситуации.То есть векторы допускаются при использовании сложения
1:2 + 3:4
# [1] 4 6
`+`(1:2, 3:4)
# [1] 4 6
Однако некоторые другие функции не векторизованы.Например,
seq(3:4, 6:7)
# Error in seq.default(3:4, 6:7) : 'from' must be of length 1
В этом случае, если вы используете outer
, взгляните на ?Vectorize
.
Некоторые операции имеют даже «более прямые» выделенные функции.Например, если бы у нас было
grid[i, j] <- i * j
Тогда вы должны использовать
inputVector1 %*% t(inputVector2)
, так как это будет быстрее и чище, чем обе петли и outer
.
Сравнение трех подходов, упомянутых ранее
microbenchmark(L.GUEGAN(), niceFor(), funOuter(), times = 2000)
# Unit: microseconds
# expr min lq mean median uq max neval cld
# L.GUEGAN() 24.354 33.8645 38.933968 35.6315 40.878 295.661 2000 c
# niceFor() 4.011 4.7820 6.576742 5.4050 7.697 29.547 2000 a
# funOuter() 4.928 6.1935 8.701545 7.3085 10.619 74.449 2000 b
Таким образом, хороший цикл for кажется даже превосходящим, если скорость имеет значение.Обратите внимание, что вы можете улучшить его, используя симметрию вашей сетки: вы можете вычислить только половину матрицы вручную, а затем использовать результаты, чтобы заполнить другой треугольник.