「R」简单理解lapply,sapply,vapply

2020-07-02 21:47:38 浏览数 (4)

在我之前转载的文章《apply,lapply,sapply用法探索》中已经对R中apply家族函数进行了比较详细地说明,这篇文章基于我在data campus中对lapplysapplyvapply几个函数的学习,以更为简单的实例来了解这几个以列表对输入的迭代函数。

使用的是一组温度数据,每天测5次,连续测量一个星期。

我们先将其输入R:

代码语言:javascript复制
temp <- list(c(3, 7, 9, 6, -1), c(6, 9, 12, 13, 5), c(4, 8, 3, -1, -3
), c(1, 4, 7, 2, -2), c(5, 7, 9, 4, 2), c(-3, 5, 8, 9, 4), c(3,
                                                             6, 9, 4, 1))

我们进行迭代计算的函数是basics,它计算每一天温度的最小、最大值、平均值以及中位数。

代码语言:javascript复制
# Definition of the basics() function
basics <- function(x) {
  c(min = min(x), mean = mean(x), median = median(x), max = max(x))
}

lapply最为常见,以列表为输入,以列表为输出。

代码语言:javascript复制
> lapply(temp, basics)
[[1]]
   min   mean median    max
  -1.0    4.8    6.0    9.0

[[2]]
   min   mean median    max
     5      9      9     13

[[3]]
   min   mean median    max
  -3.0    2.2    3.0    8.0

[[4]]
   min   mean median    max
  -2.0    2.4    2.0    7.0

[[5]]
   min   mean median    max
   2.0    5.4    5.0    9.0

[[6]]
   min   mean median    max
  -3.0    4.6    5.0    9.0

[[7]]
   min   mean median    max
   1.0    4.6    4.0    9.0

可以看出,如果迭代次数够大,结果会非常冗长,但我们所需要的结果其实可以以比较紧凑的数组(矩阵)展示出来。因此,我们可以使用sapply函数,s前缀即简化之意。

代码语言:javascript复制
> sapply(temp, basics)
       [,1] [,2] [,3] [,4] [,5] [,6] [,7]
min    -1.0    5 -3.0 -2.0  2.0 -3.0  1.0
mean    4.8    9  2.2  2.4  5.4  4.6  4.6
median  6.0    9  3.0  2.0  5.0  5.0  4.0
max     9.0   13  8.0  7.0  9.0  9.0  9.0

是否已经足够紧凑?

记得,如果你使用迭代计算的结果不是一个向量,就不要使用sapply进行简化计算。

最后想要介绍的函数vapply其实是为sapply加了一层验证选项:

代码语言:javascript复制
> vapply(temp, basics, numeric(4))
       [,1] [,2] [,3] [,4] [,5] [,6] [,7]
min    -1.0    5 -3.0 -2.0  2.0 -3.0  1.0
mean    4.8    9  2.2  2.4  5.4  4.6  4.6
median  6.0    9  3.0  2.0  5.0  5.0  4.0
max     9.0   13  8.0  7.0  9.0  9.0  9.0
> vapply(temp, basics, numeric(3))
Error in vapply(temp, basics, numeric(3)) : 值的长度必需为3,
 但FUN(X[[1]])结果的长度却是4
 ```

 读者可以发现,当第三个参数其实就是验证选项,命名为`FUN.VALUE`。

 ```R
 > args(vapply)
function (X, FUN, FUN.VALUE, ..., USE.NAMES = TRUE)
NULL

我们知道每次迭代计算应该返回4个数值型结果,所以当我们设置为numeric(3)时它会报错。这个函数及其选项的设定在我们编写比较大型的迭代计算和整合函数代码时非常有用,可以帮助我们快速检验结果的有效性,尽量避免调试bug带来的苦恼。

Once you know about vapply(), there's really no reason to use sapply() anymore. If the output that lapply() would generate can be simplified to an array, you'll want to use vapply() to do this securely. If simplification is not possible, simply stick to lapply().

1 人点赞