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

R 使用非顺序向量作为循环的输入,r,loops,vector,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)) } ns记住R中的许多函数都是矢量化的 > rnorm(length(ns), mean=ns) [1] 9.905652 19.721717 40.462751 78.

我在R中遇到了一些循环函数的问题,在这个网站上找不到关于这个问题的答案。我想使用一个数值向量作为R中循环的输入

例如:

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

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

ns记住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)))
计算出
四舍五入
并删除默认参数
sd=1
,因此

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

然后也许我们看到了完全矢量化的解

round(rnorm(n = length(ns), mean = ns))

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

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


第二个是惯用的R.

@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

ns在编码时遇到了一个类似的问题。所以我想我会给出一个更干净的循环版本。我个人会使用以下结构:

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 ##

ns您指出要避免R中的循环,但建议
sapply()
更好,这还不够具体。您的两个示例都在R中形成循环。与
相比,
sapply()
在编译代码中执行的循环稍微多一些,但是如果循环体是计算时间的主要部分,那么
sapply()就是
使用编译的循环代码在很大程度上是不相关的,两种解决方案的执行时间非常相似。对R中循环的厌恶通常是S-Plus时代的宿醉,或者是因为编写了糟糕的R代码。@GavinSimpson-感谢您的澄清。我同意在许多情况下,执行时间可能类似。我认为
sapply()
的主要优势在于它促进了更好的编码风格。实际上,我认为,对编写
for
循环的厌恶通常会导致人们编写复杂的
*应用
代码/函数,而
for()
循环则会更自然、更容易理解、更省力。
sapply(ns, function(n) round(rnorm(1, mean = n, sd = 1)))
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
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 ##