使用非顺序向量作为循环的输入

Use*_*r33 2 loops r vector

我在R中遇到循环函数的一些问题,并且在这个网站上找不到这个问题的答案.我想使用数字向量作为R中循环的输入.

例如:

ns <- c(10, 20, 40, 80, 160)

for (n in ns) {
 ni[n] <- round(rnorm(1, mean = n, sd = 1))
}
Run Code Online (Sandbox Code Playgroud)

该代码的结果是在该向量中具有155倍NA和五个正确值的向量.但是,我想摆脱所有这些NA并获得只有五个正确值的向量.我知道如何从155 NA的矢量中选择正确的值,但我更喜欢在运行循环后直接获得正确的矢量.

先感谢您!

Mar*_*gan 7

请记住,R中的许多函数都是矢量化的

> rnorm(length(ns), mean=ns)
[1]   9.905652  19.721717  40.462751  78.982971 160.770257
Run Code Online (Sandbox Code Playgroud)

(在你的问题中,ni[n]创建一个向量,只要最大值n,即160个元素).

有趣的是,这是从sapply@VictorK提供的解决方案演变而来的.

sapply(ns, function(n) round(rnorm(1, mean = n, sd = 1)))
Run Code Online (Sandbox Code Playgroud)

将因子分解出来round并删除默认参数sd = 1,所以

round(sapply(ns, function(n) rnorm(1, mean = n)))
Run Code Online (Sandbox Code Playgroud)

然后认识到,如果我们将它命名为调用中的第一个参数,则rnorm可以替换匿名函数.第一个参数被命名,所以事情有点令人困惑; 但我们强迫要匹配第二个参数的元素.例如,第一次通过我们评估的sapply .R首先按名称匹配参数,因此n = 1匹配第一个参数,然后按其余参数中的位置匹配,因此未命名参数匹配下一个可用参数,)function(n) ...sapplyrnormnnsmeanrnorm(ns[[1]], n=1)rnormns[[1]]mean

round(sapply(ns, rnorm, n = 1))
Run Code Online (Sandbox Code Playgroud)

然后我们可能会看到完全矢量化的解决方案

round(rnorm(n = length(ns), mean = ns))
Run Code Online (Sandbox Code Playgroud)


Rei*_*son 6

@Martin Morgan已经向您展示了如何针对您提供的特定示例正确地执行此操作.但是,让我们假设你想要使用一个没有矢量化的函数,或者你想要在实际例子中做其他事情.

这样做的一种方法是迭代元素的索引ns,而不是元素本身.考虑

ns <- c(10, 20, 40, 80, 160)
ni <- numeric(length = length(ns)) ## pre-allocate storage

for (n in seq_along(ns)) {
  ni[n] <- round(rnorm(1, mean = ns[n], sd = 1))
}

> ni
[1]  12  21  40  80 160
Run Code Online (Sandbox Code Playgroud)

关键的区别是

  • 使用seq_along()得到R生成一个1,2,3,...序列,只要和ns,
  • 使用n索引ns来选择正确的值而不是使用n自身的值.

对于这个例子来说,调用rnorm() lenght(ns)时间是浪费的,但是有时候做这样的事情确实有意义并且通过循环变量索引而不是使用循环变量本身是一种方便的方法.