Quiero crear una función que, dado un vector, informe otro vector con los números pares.

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

Pero esto da NULL para un número en x.

Alguien sabe lo que falta? Gracias

1
Roy_Batty 28 abr. 2020 a las 19:09

3 respuestas

La mejor respuesta

Solución 1 Será mejor utilizar las funciones de aplicación, que suelen ser más rápidas y más fáciles de usar. En tu caso será:

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

El código anterior aplicará el módulo sobre la función 2 a su matriz y devolverá solo los elementos que satisfacen el módulo sobre la condición 2 == 0.

Solución 2 Si aún desea utilizar su enfoque, entonces el error es que calcula el recordatorio (y anexa respectivamente a la matriz) para el índice (es decir, i). En cambio, debe hacer eso para el elemento de una matriz (es decir, x[i]). El código correcto será:

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
}
2
Hrant Davtyan 28 abr. 2020 a las 16:19

Creo que podría simplificar esto y acelerarlo bastante:

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

Usar lapply probablemente no sea una gran idea ya que en realidad usa bucles debajo del capó. Es mejor atenerse a la vectorización nativa de R, como puede ver en el siguiente punto de referencia:

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 
3
Allan Cameron 28 abr. 2020 a las 16:31

Una forma breve y quizás rápida de obtener los números pares de x es 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
GKi 28 abr. 2020 a las 16:48