【问题标题】:Save the output of a for loop in R在 R 中保存 for 循环的输出
【发布时间】:2019-10-24 08:25:04
【问题描述】:

假设我有一个二项分布,其中 n=12,p=0.2。我将此样本分成 4 个块(组),每个块的组大小为 3。然后我删除总和等于 0 的输出。对于剩余的输出,我要做的是将所有剩余的输出组合成一个新的向量。这是我的代码

set.seed(123)
sample1=rbinom(12,1,0.2)
chuck2=function(x,n)split(x,cut(seq_along(x),n,labels=FALSE))
chunk=chuck2(sample1,4)
for (i in 1:4){
  aa=chunk[[i]]
  if (sum(aa)!=0){
    a.no0=aa
    print(a.no0)
  }
}

这是输出:

[1] 1 1 0
[1] 0 1 0
[1] 0 1 0

我想将这三个输出组合成一个新的向量,例如:

[1] 1 1 0 0 1 0 0 1 0

但我不知道它是如何工作的,请问有什么提示吗?

【问题讨论】:

  • Explaining for loop in R的可能重复
  • chunk2 函数似乎没有必要——它最终会生成一个矩阵。请参阅我的解决方案以了解更容易理解的内容。

标签: r for-loop


【解决方案1】:
set.seed(123)
sample1=rbinom(12,1,0.2)
chuck2=function(x,n)split(x,cut(seq_along(x),n,labels=FALSE))
chunk=chuck2(sample1,4)  

int_vector <- c()

for (i in 1:4){
    aa=chunk[[i]]
    if (sum(aa)!=0){
        a.no0=aa
        int_vector <- c(int_vector, a.no0)
    }
}

int_vector
# [1] 1 1 0 0 1 0 0 1 0

【讨论】:

  • 简单明了。我比我更喜欢你的回答:)
  • 谢谢 =) 列出然后取消列出它也是我的第一个想法。但似乎总有更好的方法!
  • 如果您喜欢 heds1 的回答,您可以通过选择复选标记按钮来表示。
  • 最好重命名vector 以避免与vector(函数)的潜在冲突。 IDE 通常会处理这个问题,显然是 R,但我认为最好完全避免使用这些名称。
【解决方案2】:

创建一个list() 并为其分配一个变量名。接下来,在循环中添加该变量,然后在列表中添加append 循环值。

new_vector <- list()

for (i in 1:4){
  aa=chunk[[i]]
  if (sum(aa)!=0){
    a.no0=aa
    new_vector <- append(new_vector, a.no0)
  }
}
new_vector

这将返回:

[[1]]
[1] 1

[[2]]
[1] 1

[[3]]
[1] 0

[[4]]
[1] 0

[[5]]
[1] 1

[[6]]
[1] 0

[[7]]
[1] 0

[[8]]
[1] 1

[[9]]
[1] 0

但我认为你想要一个扁平化的向量:

as.vector(unlist(new_vector))

[1] 1 1 0 0 1 0 0 1 0

【讨论】:

    【解决方案3】:

    不能直接解决您的问题,但这可以在没有 for 循环的情况下完成:

    library(dplyr)
    set.seed(123)
    sample1 <- rbinom(12, 1, 0.2)
    
    as.data.frame(matrix(sample1, ncol = 3, byrow = TRUE)) %>% 
      mutate(test = rowSums(.), id = 1:n()) %>% 
      filter(test > 0) %>% 
      dplyr::select(-test) %>% 
      gather(key, value, -id) %>% 
      arrange(id, key) %>% 
      .$value
    

    【讨论】:

      【解决方案4】:

      没有 for 循环的两个版本。

      数据:

      set.seed(123)
      sample1 <- rbinom(12, 1, 0.2)
      

      base-R 功能版:

      split.sample1 <- split(sample1,cut(seq_along(sample1),4,labels=FALSE))
      sumf <- function(x) if(sum(x) == 0) NULL else x
      result <- unlist(lapply(split.sample1,sumf),use.names=F)
      
      > result
      [1] 1 1 0 0 1 0 0 1 0
      

      现代使用管道%&gt;%运营商版本:

      library(magrittr) # for %>% operator
      grp.indx <- cut(seq_along(sample1),4,labels=FALSE)
      split.sample1 <- sample1 %>% split(grp.indx)
      result <- split.sample1 %>% lapply(sumf) %>% unlist(use.names=F)
      
      > result
      [1] 1 1 0 0 1 0 0 1 0
      

      【讨论】:

        【解决方案5】:

        您的函数似乎将伪矩阵作为列表。而是直接从sample1 生成一个矩阵,然后输出一个向量,其中rowSums 大于0。

        set.seed(123)
        sample1 = rbinom(12, 1, 0.2)
        
        chunk_mat = matrix(sample1, ncol = 3, byrow = T)
        
        as.vector(t(chunk_mat[which(rowSums(chunk_mat) != 0), ]))
        

        这里是基准测试 - 我在全局环境中有 chuck2,但每个函数仍然必须生成 chunk 数据框/矩阵/列表,以便它们是苹果对苹果。

        Unit: microseconds
                    expr      min        lq       mean    median        uq       max neval
             cole_matrix   19.902   26.2515   38.60094   43.3505   47.4505    56.801   100
         heds_int_vector 4965.201 5101.9010 5616.53893 5251.8510 5490.9010 23417.401   100
         bwilliams_dplyr 5278.602 5506.4010 5847.55298 5665.7010 5821.5515  9413.801   100
              Simon_base  128.501  138.0010  196.46697  185.6005  203.1515  2481.101   100
          Simon_magrittr  366.601  392.5005  453.74806  455.1510  492.0010   739.501   100
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-02-02
          • 2020-10-08
          • 2018-05-24
          • 2020-05-30
          • 2017-07-14
          • 1970-01-01
          • 2012-03-30
          • 2021-02-25
          相关资源
          最近更新 更多