Улучшить производительность цикла - PullRequest
0 голосов
/ 09 мая 2020

Я изо всех сил пытаюсь улучшить производительность приведенного ниже кода, который выполняется примерно для 2M записей. Сначала состояние было внутри l oop, а теперь оно снаружи, и это принесло некоторые улучшения, но не достаточно.

У вас есть другие идеи?


if (Floor=="Yes") { 
  for (i in 1:length(X)){
     base_short_term[i] <- pmax(numeric_vector1[i],(1+numeric_vector2[i])^((numeric_vector3[i])/(1+numeric_vector4[i]))
  }
} else {
for (i in 1:length(X)){  
     base_short_term[i] <- pmin(numeric_vector5[i],(1+numeric_vector3[i])^((numeric_vector5[i])/(1+numeric_vector7[i]))
 }
}

1 Ответ

1 голос
/ 09 мая 2020

Петли плохие в R, и их следует по возможности избегать. Вот такой случай: векторизованная операция была бы намного более эффективной (циклы приводят к накладным расходам памяти) и более читаемым кодом:

df <- data.frame(x1 = numeric_vector1,
                x2 = numeric_vector2,
                x3 = numeric_vector3,
                x4 = numeric_vector4,
                x5 = numeric_vector5,
                x7 = numeric_vector7)

if (Floor == "yes"){
   df$base_short_term <- pmax(df$x1, (1+df$x2)^(df$x3/df$x4))
} else{
   df$base_short_term  <- pmin(df$x5, (1+df$x3)^(df$x5/df$x7))
}

Если циклов избежать невозможно, лучше использовать lapply или отдать предпочтение Rcpp

Обновить

Если векторы имеют разную длину, вы потеряете производительность, потому что вам нужно сначала разрезать от 1 до length(X) или использовать lapply

Нарезка вектора

df <- data.frame(x1 = numeric_vector1[seq_along(X)],
                x2 = numeric_vector2[seq_along(X)],
                x3 = numeric_vector3[seq_along(X)],
                x4 = numeric_vector4[seq_along(X)],
                x5 = numeric_vector5[seq_along(X)],
                x7 = numeric_vector7[seq_along(X)])

(это решение возможно, потому что даже если векторы не имеют одинаковой длины, вы используете только индексы до length(X) для всех ваших векторов)

lapply

Действительно выглядит как ваш for l oop, но более эффективно, поскольку позволяет избежать создания и сброса объекта на каждой итерации

Например, если Floor равно TRUE:

base_short_term <- lapply(seq_along(X), function(i), {
     pmax(numeric_vector1[i],(1+numeric_vector2[i])^((numeric_vector3[i])/(1+numeric_vector4[i]))
  })
...