R — Простой цикл не работает: нет цикла для разрыва/следующего, перехода на верхний уровень

#r #loops #break #next #microbenchmark

Вопрос:

Я знаю, что это, вероятно, простой вопрос, но я изо всех сил стараюсь учиться и совершенствоваться. Когда я пробую этот код, он выдает мне ошибку: «нет цикла для разрыва/следующего, перехода на верхний уровень». Может ли кто-нибудь подсказать, почему и помочь мне? Большое вам спасибо.

 x_1 <- rnorm(100)
x_2 <- rnorm(10000)
x_3 <- rnorm(1000000)

to_evaluate <- list(x_1, x_2, x_3)

speed_test <- for (i in to_evaluate) {
  microbenchmark(mean_loop(i), mean_mat(i), mean(i))
} 
print(speed_test)

 

Код для mean_loop и mean_mat:

 x <- c(1:11)

mean_loop <- function(x) {
  
  sum_of_x <- 0
  
  for(i in x){
    sum_of_x <- sum_of_x   x[i]
  }
  
  mean_of_x <- sum_of_x/length(x)
  return(mean_of_x)
}

mean_mat <- function(x) {
sum(diag(length(x))%*%x)/length(x)
}
 

Функция microbenchmark (из пакета microbenchmark ) позволяет измерить скорость выполнения кода. Если вы дадите ему код для оценки, он оценит его 100 раз и вернет сводную статистику о том, сколько времени потребовалось для запуска кода. Если вы дадите ему несколько выражений, он будет делать это для каждого выражения.

Комментарии:

1. Может быть, попробуем использовать for (i in length(to_evaluate) . Кроме того, рассматривали ли вы возможность использования lapply ? т. е. lapply(to_evaluate, function(x) microbenchmark(mean_loop(x), mean_mat(x), mean(x))) ? Не могли бы вы добавить пакеты , которые вы используете для функций microbenchmark() mean_loop() и mean_mat() ?

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

Ответ №1:

Это работает для меня, используя определения функций из вопроса —

 x_1 <- rnorm(10)
x_2 <- rnorm(100)
x_3 <- rnorm(1000)
library(microbenchmark)
to_evaluate <- list(x_1, x_2, x_3)

result <- vector('list', length(to_evaluate))

for (i in seq_along(to_evaluate)) {
  val <- to_evaluate[[i]]
  result[[i]] <- microbenchmark(mean_loop(val), mean_mat(val), mean(val))
} 

result

#[[1]]
#Unit: microseconds
#           expr   min     lq    mean median    uq     max neval cld
# mean_loop(val) 2.818 3.2495 7.62632  4.204 5.847  41.214   100   a
#  mean_mat(val) 2.547 2.9765 7.90376  3.571 4.940  93.155   100   a
#      mean(val) 1.896 2.1700 6.59605  2.818 4.204 116.467   100   a

#[[2]]
#Unit: microseconds
#           expr    min      lq     mean median      uq     max neval cld
 #mean_loop(val) 49.368 89.8705 92.81099 92.820 99.6505 179.400   100   c
 # mean_mat(val) 18.968 50.7335 55.61163 52.987 55.5770 141.363   100  b 
 #     mean(val)  2.090  2.2815  3.87982  2.803  3.3115  33.779   100 a  

#[[3]]
#Unit: microseconds
#           expr      min        lq       mean   median        uq       max neval cld
# mean_loop(val) 1359.527 1511.9295 3312.36578 1835.326 2970.1350 16455.048   100   b
#  mean_mat(val) 1713.178 2155.3815 4032.53143 2352.858 2739.6650 19783.264   100   b
#      mean(val)    3.708    4.6695   16.39451   14.881   21.8355   162.184   100  a 
 

Ответ №2:

Используя lapply() вы могли бы сделать:

 speed_test <- lapply(to_evaluate, function(x) microbenchmark(mean_loop(x), mean_mat(x), mean(x)))
print(speed_test)
 

Пример:

 # had to remove x_3 to overcome a crash not linked with the use of a loop or lapply, see the Note at the end of the post
x_1 <- rnorm(100)
x_2 <- rnorm(10000)
to_evaluate <- list(x_1, x_2)

library(microbenchmark)

speed_test <- lapply(to_evaluate, function(x) microbenchmark(mean_loop(x), mean_mat(x), mean(x)))
 

Выход:

 > print(speed_test)

[[1]]
Unit: microseconds
         expr  min    lq   mean median   uq    max neval cld
 mean_loop(x) 35.3 36.05 67.174  36.85 37.3 3000.9   100   a
  mean_mat(x) 19.7 20.25 38.090  20.60 20.9 1761.0   100   a
      mean(x)  2.0  2.30  2.793   2.70  2.9   13.8   100   a

[[2]]
Unit: microseconds
         expr      min        lq       mean    median        uq      max neval cld
 mean_loop(x) 126214.8 139520.40 211537.906 182460.50 245618.95 463139.9   100  b 
  mean_mat(x) 275451.1 314082.60 337446.084 340836.75 358470.35 411152.0   100   c
      mean(x)     16.7     20.15     31.192     33.35     35.35     82.0   100 a  
 

Примечание:

Независимо от того, использую ли я loop of lapply на своем компьютере, я сталкиваюсь с проблемой производительности, не связанной с вашим вопросом. Т. е. даже это не работает для меня microbenchmark(mean_loop(to_evaluate[[3]]), mean_mat(to_evaluate[[3]]), mean(to_evaluate[[3]])) , в то время как другие работают нормально (с to_evaluate[[1]] и to_evaluate[[2]] ).

Комментарии:

1. Привет, Пол! Спасибо! Я пытался, но ошибка «нет цикла для разрыва/следующего, переход на верхний уровень» продолжает появляться. Я думаю, что ошибка на самом деле находится внутри microbenchmark().

2. @CeciliaBonucchi Код, представленный в этом ответе, работает для меня и выдает показанный результат :/ Однако по некоторым причинам, если я включу пользовательские функции mean_mat() , и mean_loop() он выйдет из строя, но по другой причине, чем та, на которую вы указываете

3. Я только что проверил и получил те же самые рассуждения. Я думаю, что microbenchmark не может выполнять несколько функций одновременно. Как вы думаете, мне нужна вложенная петля или вложенный цикл? Не могли бы вы попытаться помочь мне его построить? Огромное спасибо

4. @CeciliaBonucchi, Ронак решил вашу проблему с циклом, я думаю, поэтому я сосредоточил свой ответ на идее, lapply однако я не могу проверить ее из-за другой проблемы, которая не связана с вашим вопросом. Мне кажется microbenchmark() , что я действительно могу обрабатывать несколько функций одновременно.

5. Большое вам спасибо за все усилия, которые вы приложили, чтобы помочь мне! Я постараюсь, чтобы ваш код (который действительно интересен) работал и для x_3! Еще раз спасибо!!