请记住,R中的许多函数是矢量化的。
> rnorm(length(ns), mean=ns)
[1] 9.905652 19.721717 40.462751 78.982971 160.770257
在你的问题中,
ni[n]
创建一个长度为最大值
n
的向量,即160个元素。
很有趣看到这个问题从@VictorK提出的
sapply
解决方案逐渐发展。
sapply(ns, function(n) round(rnorm(1, mean = n, sd = 1)))
将round
因子化并删除默认参数sd = 1
,如下:
round(sapply(ns, function(n) rnorm(1, mean = n)))
然后认识到如果在sapply
函数调用中给rnorm
命名第一个参数,那么rnorm
可以替代匿名函数function(n) ...
。 rnorm
的第一个参数被命名为n
,因此有些混淆;但是我们强制让ns
的元素匹配第二个参数mean
。例如,在第一次sapply中,我们会评估rnorm(ns[[1]], n=1)
。R首先通过名称匹配参数,因此n=1
与rnorm
的第一个参数匹配,然后通过剩余参数的位置进行匹配,因此未命名的参数ns[[1]]
匹配下一个可用的参数mean
。
round(sapply(ns, rnorm, n = 1))
然后也许我们会看到完全矢量化的解决方案。
round(rnorm(n = length(ns), mean = ns))
sapply()
并不够具体。你的两个例子在R中都形成了循环,只是恰好sapply()
在编译代码中处理了更多的循环。但是,在循环体占主导计算时间的情况下,sapply()
使用编译循环代码的优势基本可以忽略不计,并且这两种解决方案的执行时间非常相似。R中对循环的厌恶常常源于S-Plus时代或者编写糟糕的R代码。 - Gavin Simpsonsapply()
的主要优点是它促进了更好的编程风格。 - Victor K.for
循环的厌恶常常会导致人们编写复杂的*apply
代码/函数,而使用for()
循环会更自然、更容易理解,也更省力。 - Gavin Simpson