在 R 中的向量中选择偶数的函数

Roy*_*tty 2 for-loop r function

我想创建一个函数,给定一个向量,用偶数报告另一个向量。

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

但这给出 NULL了 x 中的一个数字。

有人知道缺少什么吗?谢谢

All*_*ron 5

我认为你可以简化这个并加快很多速度:

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

使用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 
Run Code Online (Sandbox Code Playgroud)


小智 4

解决方案 1 您会更好地使用应用函数,这些函数通常更快且更用户友好。在你的情况下它将是:

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

上面的代码将对数组应用模数超过 2 的函数,并仅返回满足模数超过 2 == 0 条件的元素。

解决方案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
}
Run Code Online (Sandbox Code Playgroud)

  • `lapply` 确实是对向量进行“数学计算”的过度设计。(不可否认,“for”循环也是如此,但家庭作业就是家庭作业。)(一般来说)要注意“增长对象”,即迭代地附加到向量(以及列表和框架)从长远来看扩展性很差;参见 [R Inferno](https://www.burns-stat.com/pages/Tutor/R_inferno.pdf) 的第 2 章,标题为“Growing Objects”。 (3认同)