9.5 多个输入的应用函数

lapply的缺点之一是它的函数参数只能循环作用于单个向量参数。另一个缺点是:对于作用于每个元素的函数,你不能访问该元素的名称。

mapply是“多参数列表应用(multiple argument list apply)”的简称,它能让你传入尽可能多的向量作为参数,这解决了上面的第一个问题。常见的用法是传入一个列表,再传入另一个列表作为前者的名字,这就解决了第二个问题。有点烦人的是,为了容纳任意数目的向量参数,参数的顺序被改变了。对于mapply,每一个传递的参数都是函数:

  1. msg <- function(name, factors)
  2. {
  3. ifelse(
  4. length(factors) == 1,
  5. paste(name, "is prime"),
  6. paste(name, "has factors", toString(factors))
  7. )
  8. }
  9. mapply(msg, names(prime_factors), prime_factors)
  10. ## two three
  11. ## "two is prime" "three is prime"
  12. ## four five
  13. ## "four has factors 2, 2" "five is prime"
  14. ## six seven
  15. ## "six has factors 2, 3" "seven is prime"
  16. ## eight nine
  17. ## "eight has factors 2, 2, 2" "nine has factors 3, 3"
  18. ## ten
  19. ## "ten has factors 2, 5"

在默认情况下,mapplysapply的表现相同,且会尽量地简化输出。通过传递参数SIMPLIFY = FALSE可以关闭此行为(使它表现得更像lapply)。

即时向量化(Instant Vectorization)

Vectorizemapply的包装函数。通常它接受一个标量作为输入参数,并返回一个新的接受向量的函数。下一个函数不是向量化的,因为它使用了switch,而这需要它的输入参数为标量:

  1. baby_gender_report <- function(gender)
  2. {
  3. switch(
  4. gender,
  5. male = "It's a boy!",
  6. female = "It's a girl!",
  7. "Um..."
  8. )
  9. }

如果把向量传入到函数中,则会抛出一个错误:

  1. genders <- c("male", "female", "other")
  2. baby_gender_report(genders)

从理论上说,完全可以重写一个函数,使它变成向量化的。但更简单的方法是使用Vectorize函数:

  1. vectorized_baby_gender_report <- Vectorize(baby_gender_report)
  2. vectorized_baby_gender_report(genders)
  3. ## male female other
  4. ## "It's a boy!" "It's a girl!" "Um..."