3

我在 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

4 回答 4

7

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

> rnorm(length(ns), mean=ns)
[1]   9.905652  19.721717  40.462751  78.982971 160.770257

(在您的问题中,ni[n]创建一个与 的最大值相同的向量n,即 160 个元素)。

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

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

分解round并删除默认参数sd = 1,所以

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

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

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

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

round(rnorm(n = length(ns), mean = ns))
于 2013-01-29T21:15:43.453 回答
7

@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

主要区别是

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

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

于 2013-01-29T21:30:48.110 回答
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。

于 2013-01-29T21:25:17.133 回答
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 ##
于 2018-12-25T14:19:13.457 回答