Функция выбора четных чисел в векторе в R - PullRequest
1 голос
/ 28 апреля 2020

Я хочу создать функцию, которая, учитывая вектор, сообщает о другом векторе с четными числами.

evens <- function(x){
  vector <- c()
  for (i in 1:length(x)){
    if (i %% 2 == 0){
      vector[i] <- vector[i] + i
    }
  }
  vector
}

Но это дает NULL для числа в x.

Кто-нибудь знает, чего не хватает? Спасибо

Ответы [ 3 ]

3 голосов
/ 28 апреля 2020

Я думаю, вы могли бы упростить это и значительно ускорить его:

evens <- function(x) subset(x, x %% 2 == 0)
evens(1:10)
#> [1]  2  4  6  8 10

Использование lapply, вероятно, не очень хорошая идея, поскольку на самом деле используются петли под капотом. Лучше всего придерживаться нативной векторизации R, как вы можете видеть из следующего теста:

evens1 <- function(some_array) some_array[lapply(some_array, "%%", 2) == 0]
microbenchmark::microbenchmark(evens1(1:10000), evens(1:10000))
#> Unit: microseconds
#>             expr      min       lq      mean   median       uq       max neval cld
#>  evens1(1:10000) 5694.309 5883.195 6359.1855 6039.232 6306.992 14811.840   100   b
#>   evens(1:10000)  757.942  770.944  788.6802  785.317  799.346   912.267   100  a 
2 голосов
/ 28 апреля 2020

Короткий и, возможно, быстрый способ получения четных чисел из x - x[!x%%2].

evens.HrantDavtyan <- function(x) x[lapply(x, "%%", 2) == 0]
evens.HrantDavtyan2 <- function(x){
  vector <- c()
  for (i in 1:length(x)){
    if (x[i] %% 2 == 0){ #this was the first error line
      vector <- c(vector, x[i]) ##this was the seconds error line
    }
  }
  vector
}
evens.AllanCameron <- function(x) subset(x, x %% 2 == 0)
evens.r2evans <- function(x) x[ x %% 2 == 0]
evens.GKi <- function(x) x[!x%%2]
x <- 1:10000
microbenchmark::microbenchmark(evens.HrantDavtyan(x), evens.HrantDavtyan2(x), evens.AllanCameron(x), evens.r2evans(x), evens.GKi(x), control=list(order="block"))
#Unit: microseconds
#                   expr       min         lq       mean     median         uq       max neval
#  evens.HrantDavtyan(x)  3163.272  3222.8030  3938.6202  3269.1015  3527.5345 33867.486   100
# evens.HrantDavtyan2(x) 26009.475 28061.4230 28196.7498 28275.5705 28794.2855 30856.206   100
#  evens.AllanCameron(x)   239.599   240.4480   257.7027   240.9265   243.7575  1715.947   100
#       evens.r2evans(x)   199.506   200.2945   202.1106   200.7690   203.7865   224.104   100
#           evens.GKi(x)   191.303   191.7400   193.2737   192.1310   193.2295   217.001   100
2 голосов
/ 28 апреля 2020

Решение 1 Вам будет лучше использовать функции применения, которые обычно быстрее и удобнее для пользователя. В вашем случае это будет:

some_array <- c(1,4,5,7,8)
some_array[lapply(some_array, "%%", 2) == 0]

Приведенный выше код будет применять функцию модуля 2 к вашему массиву и возвращать только те элементы, которые удовлетворяют условию модуля 2 +=.

Решение 2 Если вы все еще хотите использовать свой подход, то ошибка в том, что вы вычисляете напоминание (и, соответственно, добавление в массив) для индекса (то есть i). Вместо этого вы должны сделать это для элемента массива (т.е. x[i]). Правильный код будет:

evens <- function(x){
  vector <- c()
  for (i in 1:length(x)){
    if (x[i] %% 2 == 0){ #this was the first error line
      vector <- c(vector, x[i]) ##this was the seconds error line
    }
  }
  vector
}
...