Этот вид вычислений не может использовать преимущество векторизации R из-за итеративных зависимостей. Но замедление, похоже, действительно связано с индексированием производительности на data.frame
или data.table
.
Интересно, что мне удалось значительно ускорить l oop, открыв a
, b
и y
непосредственно как цифры c vectors
(преимущество в 1000 раз больше для 2 * 10 ^ 5 строк) или matrix
"столбцов" (преимущество в 100 раз больше для 2 * 10 ^ 5 строк) по сравнению со столбцами в data.table
или data.frame
.
Это старое обсуждение может все же пролить некоторый свет на этот довольно удивительный результат: https://stat.ethz.ch/pipermail/r-help/2011-July/282666.html
Обратите внимание, что я также сделал другую игрушку data.frame
, поэтому я можно протестировать более крупный пример, не возвращая Inf
при росте y
с i
:
Option data.frame
(число c векторов, встроенных в data.frame
или data.table
для вашего примера) :
vec_length <- 200000
dt <- data.frame(a=seq(from=0, to=1, length.out = vec_length), b=seq(from=0, to=-1, length.out = vec_length), y=0)
system.time(for (i in 2:nrow(dt)) {
dt$y[i] <- (dt$y[i - 1] + dt$b[i]) * dt$a[i]
})
#user system elapsed
#79.39 146.30 225.78
#NOTE: Sorry, I didn't have the patience to let the data.table version finish for vec_length=2*10^5.
tail(dt$y)
#[1] -554.1953 -555.1842 -556.1758 -557.1702 -558.1674 -559.1674
Опция vector
(numeric
векторы, извлеченные до l oop):
vec_length <- 200000
dt <- data.frame(a=seq(from=0, to=1, length.out = vec_length), b=seq(from=0, to=-1, length.out = vec_length), y=0)
y <- as.numeric(dt$y)
a <- as.numeric(dt$a)
b <- as.numeric(dt$b)
system.time(for (i in 2:length(y)) {
y[i] <- (y[i - 1] + b[i]) * a[i]
})
#user system elapsed
#0.03 0.00 0.03
tail(y)
#[1] -554.1953 -555.1842 -556.1758 -557.1702 -558.1674 -559.1674
Опция matrix
(data.frame
, преобразованная в * 1038) * до l oop):
vec_length <- 200000
dt <- as.matrix(data.frame(a=seq(from=0, to=1, length.out = vec_length), b=seq(from=0, to=-1, length.out = vec_length), y=0))
system.time(for (i in 2:nrow(dt)) {
dt[i, 1] <- (dt[i - 1, 3] + dt[i, 2]) * dt[i, 1]
})
#user system elapsed
#0.67 0.01 0.69
tail(dt[,3])
#[1] -554.1953 -555.1842 -556.1758 -557.1702 -558.1674 -559.1674
#NOTE: a matrix is actually a vector but with an additional attribute (it's "dim") that says how the "matrix" should be organized into rows and columns
Опция data.frame
с индексированием в матричном стиле:
vec_length <- 200000
dt <- data.frame(a=seq(from=0, to=1, length.out = vec_length), b=seq(from=0, to=-1, length.out = vec_length), y=0)
system.time(for (i in 2:nrow(dt)) {
dt[i, 3] <- (dt[(i - 1), 3] + dt[i, 2]) * dt[i, 1]
})
#user system elapsed
#110.69 0.03 112.01
tail(dt[,3])
#[1] -554.1953 -555.1842 -556.1758 -557.1702 -558.1674 -559.1674