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

时间:2013-01-29 21:12:19

标签: r loops vector

我在R中遇到环路功能的一些问题,但在本网站上找不到这个问题的答案。我想使用数字向量作为R中循环的输入。

例如:

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

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

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

提前谢谢!

4 个答案:

答案 0 :(得分:7)

请记住,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)))

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

mean

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

round(sapply(ns, rnorm, n = 1))

答案 1 :(得分:6)

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

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

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

关键区别是

  • 使用seq_along()让R生成1,2,3,......序列,其长度与ns一样长,
  • 使用n作为ns的索引来选择正确的值,而不是使用n本身的值。

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

答案 2 :(得分:2)

有几种方法可以动态创建矢量。以下是一些选项:

1)使用循环(但请参阅下一个解决方案,因为您应该尝试避免R中的循环):

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

ni <- numeric(length(ns)) # pre-allocate the resulting vector
for (i in 1:length(ns)) {
  ni[i] <- round(rnorm(1, mean = ns[i], sd = 1))
}

2)使用apply系列函数:

sapply(ns, function(n) round(rnorm(1, mean = n, sd = 1)))

第二个是惯用的R。

答案 3 :(得分:1)

在编码时偶然发现了类似的问题。所以我想我会给出一个更干净的循环版本。我个人将使用以下构造:

ns <- c(10, 20, 40, 80, 160)
ni <- numeric(length = length(ns))  # keeping this as per Victor's earlier post#

y=0  #adding starting counter#
 for (i in ns) {  # ns is already defined with its numeric sequence  on line 1 of the  
                  # code #

   y=y+1 # counter used in the ni vector

  ni[[y]] <- meanX(i)  # preferable to create a custom function but not mandatory
 }

ni  # will produce only the 5 outputs of the rnorm function
    # 11  21  41  81 161


## Custom function  ##
meanX <-function(meanX) {round(rnorm(1, mean = meanX, sd = 1))

  return(round(rnorm(1, mean = meanX, sd = 1)))

  }
##  end of Custom function ##