【问题标题】:How to store the results of a for-loop in R when the result is a vector当结果是向量时如何在R中存储for循环的结果
【发布时间】:2020-07-24 06:26:12
【问题描述】:

在循环生成向量的函数时,我只是希望能够将生成的向量存储为一个长向量。

这不起作用:

n_total <- 5
grps <- 2
start_s <- 0.7
start_v <- 0.8
Alpha <- 0.9

cols <- vector()
for(i in seq(grps)){
  if(i > 1){
    start_s <- start_s-0.1
    start_v <- start_v-0.1
  }
  cols[i] <- rainbow(n_total, start_s, start_v, alpha = Alpha)
}

所以cols中存储的结果应该是:

[1] "#B34747E6" "#9DB347E6" "#47B372E6" "#4772B3E6" "#9D47B3E6" "#994D4DE6" "#8A994DE6" "#4D996BE6" "#4D6B99E6" "#8A4D99E6"

即一个 1x10 的字符串向量。

【问题讨论】:

    标签: r string for-loop vector


    【解决方案1】:

    我们可以在这里使用mapply

    n_total <- 5
    grps <- 2
    start_s <- 0.7
    start_v <- 0.8
    Alpha <- 0.9
    
    
    inds <- seq(0, by = 0.1, length.out = grps)
    c(mapply(function(x, y) rainbow(n_total, x, y, alpha = Alpha), 
             start_s - inds, start_v - inds))
    
    #[1] "#B34747E6" "#9DB347E6" "#47B372E6" "#4772B3E6" "#9D47B3E6" 
    #    "#994D4DE6" "#8A994DE6" "#4D996BE6" "#4D6B99E6" "#8A4D99E6"
    

    【讨论】:

      【解决方案2】:

      也许这不是您所期望的(放置了 for-loop 标签),但您应该尽可能避免使用 R for 循环。相反,习惯于使用矢量化操作进行迭代。它们效率更高,并产生更易读的代码。一种选择是使用mapply,这是另一种使用mappurrr 包)的方法。

      tibble 函数为迭代创建基础(如果您愿意,可以创建迭代器)。

      mutatemap 的组合实际上是运行rainbow 函数并将其结果保存在tibble 中。

      结果以列表中的列表形式提供(tibble 中的字符向量列),因此unnest 用于将它们提取回常规向量。

      最终,要将其作为一个简单的向量,您可以使用answer_tib$rainbow_val

      请注意,您在问题中提供的输出与您应该得到的输出不一致。不清楚为什么您可能打算为 start_sstart_v 使用不同的值?

      library(tidyverse)
      
      n_total <- 5
      set_alpha <- 0.9
      start_s <- 0.7
      start_v <- 0.8
      
      answer_tib <- tibble(run_index = seq(0, 0.1, by = 0.1)) %>% 
        mutate(rainbow_val = map(run_index, ~{
          rainbow(n = n_total, start_s - .x, start_v - .x, alpha = set_alpha)
        })) %>% 
        unnest(rainbow_val)
      
      answer_tib$rainbow_val
      #>  [1] "#CC3D3DE6" "#AFCC3DE6" "#3DCC76E6" "#3D76CCE6" "#AF3DCCE6" "#B34747E6"
      #>  [7] "#9DB347E6" "#47B372E6" "#4772B3E6" "#9D47B3E6"
      

      【讨论】:

        【解决方案3】:

        在 OP 的帖子中,'cols' 用 length 0 初始化。这里的一个选项是在每次迭代中分配向量时附加向量

        cols <- vector()
        for(i in seq(grps)){
        if(i > 1){
         start_s <- start_s-0.1
          start_v <- start_v-0.1
          }
          cols<- c(cols, rainbow(n_total, start_s, start_v, alpha = Alpha))
        }
        
        
        cols
        #[1] "#CC3D3DE6" "#AFCC3DE6" "#3DCC76E6" "#3D76CCE6" "#AF3DCCE6" "#B34747E6" "#9DB347E6" "#47B372E6"
        #[9] "#4772B3E6" "#9D47B3E6"
        

        如果 OP 想要运行的不是固定的 0.1 来减去

        cols <- vector()
        i1 <- seq(0, by = 0.1, length.out = grps)
        for(i in seq_len(grps)) {
           if(i > 1){
            start_s <- start_s-i1[i]
             start_v <- start_v-i1[i]
             }  
             cols<- c(cols, rainbow(n_total, start_s, start_v, alpha = Alpha))
          }
        
        
        
        cols
        #[1] "#B34747E6" "#9DB347E6" "#47B372E6" "#4772B3E6" "#9D47B3E6" "#994D4DE6" "#8A994DE6" "#4D996BE6"
        #[9] "#4D6B99E6" "#8A4D99E6"
        

        相反,使用预先确定的长度进行初始化然后进行索引分配会更有效。但是,这里有一些不确定的事情,即它正在执行if 检查,并且只有当它是 TRUE 时,它才会执行分配

        cols <- character(10)
        

        注意:OP 在这里要求 for 循环。在R中,有更好的方法来处理它而不是for循环

        【讨论】:

        • 我同意“注意:OP 在这里要求一个 for 循环”,但是,我认为从教育的角度来看,提供 OP 要求的内容是错误的,至少没有提到它是不是使用for 循环完成它的最佳实践。也许您应该在解决方案中提及这一点(或者甚至提供替代方案)以使其更加完整。
        猜你喜欢
        • 2021-01-03
        • 1970-01-01
        • 2014-12-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-06
        • 1970-01-01
        相关资源
        最近更新 更多