9.2 replication

第4章介绍的rep函数能把输入的参数重复数次。另一个相关函数replicate则能调用表达式数次。大多数情况下它们基本相等,只有当使用随机数时才会出现不同。现在,假定生成均匀分布随机数的runif函数不是矢量化的,那么rep函数每次都将重复相同的随机数,而replicate每次的结果都不相同(由于历史的原因,其参数顺序竟然是从后到前的,这有点烦人):

  1. rep(runif(1), 5)
  2. ## [1] 0.04573 0.04573 0.04573 0.04573 0.04573
  3. replicate(5, runif(1))
  4. ## [1] 0.5839 0.3689 0.1601 0.9176 0.5388

在更为复杂的例子中,replicate会大显身手。例如,在蒙特卡罗(Monte Carlo)分析中——replicate最主要的用途,你需要重复固定次数的分析过程且每次迭代都是相互独立的。

下一个例子将分析某人上下班时使用不同交通工具所花费的时间。这有些复杂,不过这是为了展示replicate的作用,它非常适合于这种场景。

time_for_commute函数用sample随机挑选一种交通工具(小汽车、公交车或自行车),然后用rnormrlnorm找到一个正态分布或对数正态分布1的行程时间(具体参数取决于所选的交通工具)。

1 对数正态分布偶尔会扔出非常大的数字,从而接近高峰期塞车。

  1. time_for_commute <- function()
  2. {
  3. #选择当时所用的交通工具
  4. mode_of_transport <- sample(
  5. c("car", "bus", "train", "bike"),
  6. size = 1,
  7. prob = c(0.1, 0.2, 0.3, 0.4)
  8. )
  9. #根据交通工具,找到出行的时间
  10. time <- switch(
  11. mode_of_transport,
  12. car = rlnorm(1, log(30), 0.5),
  13. bus = rlnorm(1, log(40), 0.5),
  14. train = rnorm(1, 30, 10),
  15. bike = rnorm(1, 60, 5)
  16. )
  17. names(time) <- mode_of_transport
  18. time
  19. }

switch语句的存在使得这个函数很难被向量化。这意味着:为了找到上下班时间的分布,我们需要多次调用time_for_commute来生成每天的数据。replicate使我们能即刻进行向量化:

  1. replicate(5, time_for_commute())
  2. ## bike car train bus bike
  3. ## 66.22 35.98 27.30 39.40 53.81