【问题标题】:Explaining a for loop in R解释 R 中的 for 循环
【发布时间】:2023-04-10 09:16:01
【问题描述】:

我对 R 很陌生,对 R 编程也很陌生。我有以下问题及其答案(不是我的)。我试图理解为什么有些值,从哪里获得,为什么使用它们等等。

问题:使用 for 循环制作向量 3 5 7 9 11 13 15 17。开始 用 x=numeric() 并用 for 循环填充这个向量

我知道我必须创建 x=numeric() 以便我可以用从循环获得的结果填充它。

一位同学的回答是:

> x <- numeric()
> for(i in 1:8){   
      if(i==1){                ## Why ==1 and not 0, or any other value   
          x[i] <- 3              
      }else{   
          x[i] <- x[i-1]+2  ### And why i-1   
     }

我在以下问题中遇到了类似的问题:

创建一个将向量的第二个元素添加到第一个元素的 for 循环, 从结果中减去第三个元素,再次加上第四个元素,然后 以此类推整个向量的长度

到目前为止,我创建了向量和空向量

> y = c(5, 10, 15, 20, 25, 30)
> answer <- 0 

然后,当我尝试执行 for 循环时,我被困在这里:

for(i in 1:length(y)){
if(i...){ ### ==1? ==0?
    answer = y[i]   ###and here I really don't know how to continue. 
}else if()
}

相信我,当我告诉您时,我已经阅读了对这里问题的一些回复,例如在 How to make a vector using a for loop 中,以及关于 for 循环的页面和页面,但无法真正弄清楚如何解决这些(和其他)问题。
我再说一遍,我很新,所以我很难理解它。任何帮助将不胜感激。

【问题讨论】:

  • 谁在教你,请从 SO r-tag 社区告诉他们,请停止教如何在循环中生长对象。
  • 还告诉他们阅读The R Inferno 以了解@Roland 建议“停止教授如何在循环中生长对象”的原因。
  • 就此而言,请告诉您的同学,将条件 if(i == 1) 放入循环中是很疯狂的。如果向量的第一个值不遵循余数的模式,请在循环外初始化并执行for(i = 2:n)
  • @CarlWitthoft 那么我们在什么时候教他们使用1:length(y) 来获取一组要迭代的索引是一个坏主意(即当y 的长度可能为0 时)? (对于未来的读者,seq_along(y) 更安全,因为即使y 的长度为 0,它也会给出预期的结果。)
  • @BrianDiggs 好吧,从哲学上讲,我更喜欢在使用 y 做任何事情之前检查 length(y) 是否有用:-)

标签: r for-loop vector


【解决方案1】:

首先,我将注释循环以回答循环在做什么。

# Initialize the vector
x <- numeric()
for(i in 1:8){   
  # Initialize the first element of the vector, x[1].  Remember, R indexes start at 1, not 0.
  if(i==1){                
    x[i] <- 3              
  } else {   
    # Define each additional element in terms of the previous one (x[i - 1]
    # is the element of x before the current one.
    x[i] <- x[i-1]+2  ### And why i-1   
  }
} 

使用循环并使其增长(如指令状态)的更好解决方案是这样的:

x <- numeric()
for(i in 1:8){
  x[i] <- 2 * i + 1
}

这仍然不是一个好方法,因为在循环中增长向量非常慢。为了解决这个问题,你可以通过告诉numeric你想要的向量的长度来预先分配向量:

x <- numeric(8)

解决这个问题的最佳方法是:

2 * 1:8 + 1

使用矢量化操作。

为了帮助您解决其他问题,我建议将循环的每个步骤写成表格。例如,对于我的解决方案,表格是

i | x[i]
------------------
1 | 2 * 1 + 1 = 3
2 | 2 * 2 + 1 = 5

等等。这将使您了解 for 循环在每次迭代中的作用。

【讨论】:

    【解决方案2】:

    这不是一个答案,因为有比 for 循环更好的方法来解决交替符号求和问题。我认为熟悉 for 循环可能是有价值的,但也应该学习 R 中的向量化方法。 R 的许多操作都有“参数回收”,包括“*”(乘法)操作:看:

     (1:10)*c(1,-1)
    

    然后取一个任意向量,比如vec 并尝试:

    sum( vec*c(1,-1) )
    

    查看该结果后更正确的答案是:

    vvec[1] + sum( vec[-1]*c(1,-1) )
    

    这具有说明 R 的负索引的教育优势。在您的文档中查找“参数回收”。较短的对象会被自动复制/三重复制/然而-许多需要-cated 以完全匹配数学或逻辑表达式中最长向量的长度。

    【讨论】:

    • 我认为 for 循环在开始时更容易,因为您可以告诉 R 按照您的想法做某事。在 R 中使用向量化时,您首先必须了解 R 的想法,然后更改您的方法以适应 R。而且我认为不提预分配 @Roland 或优化也不错,因为当人们在学习时(嗯,至少对我来说),我并没有陷入使用大型数据库的情况,在这种情况下优化代码和担心内存管理至关重要。
    • @rawr 我不完全同意。预分配很容易解释。人们仍然可以证明增长对象是可能的,但是在教授了预分配并清楚地解释了为什么应该避免它之后。
    • 它可以用一两句话解释,是以后的好习惯,所以你可能是对的。
    • 感谢大家的回复!帮了大忙!
    猜你喜欢
    • 1970-01-01
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    • 2016-08-20
    • 2023-01-07
    • 2013-08-31
    • 1970-01-01
    • 2013-08-17
    相关资源
    最近更新 更多