【问题标题】:Storing a nested for loop into a single vector in R将嵌套的for循环存储到R中的单个向量中
【发布时间】:2021-08-18 07:15:16
【问题描述】:

假设我有以下代码

b = 1:3
m = 5

for(j in 1:2){
  for(i in 1:5){
    print((1-i/m)* b[j] + (i/m)* b[j+1])
  }
}

如果我打印这个,我会得到以下输出

[1] 1.2
[1] 1.4
[1] 1.6
[1] 1.8
[1] 2
[1] 2.2
[1] 2.4
[1] 2.6
[1] 2.8
[1] 3

但是,现在我想将此数据存储到单个列向量中。 当我用 print 代替空向量或列表 z[i]

【问题讨论】:

    标签: r for-loop nested nested-for-loop


    【解决方案1】:

    基础 R,sapply

    b = 1:3
    m = 5
    
    df <- sapply(1:2,function(j){
      sapply(1:5,function(i){
        out <- (1-i/m)* b[j] + (i/m)* b[j+1]
        return(out)
      })
    })
    
    result <- c(df[c(1:5),c(1:2)]) 
    

    结果

    [1] 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0
    

    速度测试 - sapply 与 for 循环

    b = 1:10001
    m = 5
    
    > system.time({ 
    + df <- sapply(1:10000,function(j){
    +   sapply(1:5,function(i){
    +     out <- (1-i/m)* b[j] + (i/m)* b[j+1]
    +     return(out)
    +   })
    + })
    + })
       user  system elapsed 
       0.19    0.00    0.19 
     
    > system.time({ 
    + out <- c()
    + for(j in 1:10000){
    +   for(i in 1:5){
    +     out <- c(out, (1-i/m)* b[j] + (i/m)* b[j+1])
    +   }
    + }
    + })
       user  system elapsed 
       3.00    0.02    3.02 
    

    【讨论】:

    • *apply 函数通常不会比 for 循环快很多。它们实际上调用了它们内部的循环。使用 apply 函数的主要优点是清晰和可读性,而不是速度。即使是嵌套的应用程序也不会胜过嵌套的 for 循环。您的示例非常复杂,因此与原始嵌套 for 循环相比没有任何优势。
    • 应用函数也不会同时运行线程。
    • @GuedesBF 我只是尝试在顶部循环中使用计时器和 1:10000 运行它,如果我添加一个循环,我的代码得到“0.19”秒,双 for 循环得到 3.00 秒额外的零我的代码是 1.84 秒,而循环没有完成,我确信这与线程有关,但也许这是 for 循环必须为每次运行覆盖向量的方式imgur.com/2l2ZCtk
    • @GuedesBF 删除了我的解释,所以我不会传播错过的信息,谢谢
    • 有一些关于应用和循环性能的有趣讨论:stackoverflow.com/questions/42393658/…stackoverflow.com/questions/2275896/…
    【解决方案2】:

    我们可以启动一个向量并将输出附加到它

    out <- c()
     for(j in 1:2){
      for(i in 1:5){
        out <- c(out, (1-i/m)* b[j] + (i/m)* b[j+1])
      }
    }
    
    df1 <- data.frame(out)
    

    -输出

    df1
       out
    1  1.2
    2  1.4
    3  1.6
    4  1.8
    5  2.0
    6  2.2
    7  2.4
    8  2.6
    9  2.8
    10 3.0
    

    或者另一个选项是来自base Router

    out <- c(t( outer(1:2, 1:5, FUN = function(j, i) (1-i/m)* b[j] + (i/m)* b[j+1])))
    

    -输出

    out
    #[1] 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0
    

    或使用expand.grid (R 4.1.0)

    expand.grid(j = 1:2, i = 1:5) |> 
          transform(out = (1-i/m)*b[j] + (i/m) * b[j + 1]) |> 
          subset(select = out)
       out
    1  1.2
    2  2.2
    3  1.4
    4  2.4
    5  1.6
    6  2.6
    7  1.8
    8  2.8
    9  2.0
    10 3.0
    

    基准测试

    
    j1 <- 1:200
    i1 <- 1:500
    # // outer 
    system.time({
     out <- c(t( outer(j1, i1, FUN = function(j, i) (1-i/m)* b[j] + (i/m)* b[j+1])))
    
    })
    #  user  system elapsed 
    #  0.004   0.000   0.004 
    
    # // sapply
    
    system.time({
    out2 <- sapply(j1,function(j){
      sapply(i1,function(i){
        out <- (1-i/m)* b[j] + (i/m)* b[j+1]
        return(out)
      })
    })
    })
    # user  system elapsed 
    #  0.152   0.004   0.155 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-22
      • 1970-01-01
      • 2020-01-29
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多