【问题标题】:R - loop and break after value found for each RowsR - 为每行找到值后循环和中断
【发布时间】:2015-09-07 02:45:51
【问题描述】:

我有一个 0-1 的矩阵。 我想做的是循环进入这个矩阵并搜索 1。 每次找到 1 时,只需 跳转 或通过该行,以便每行仅记录 1 个值。

我想知道序列的第一集是否是1。 我在想可能有一个解决方案

break 

但我不确定如何正确使用它。

所以这是我的第一个矩阵

SoloNight = structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 1, 0, 0), .Dim = 10:11)

这是我的空矩阵——记录1

matSolo = matrix(0, nrow = nrow(SoloNight), ncol = ncol(SoloNight) ) 

这是我的循环尝试

for(i in 1:nrow(matSolo)){
  for(j in 1:ncol(matSolo)){
    if(SoloNight[i,j] == 1) break
    {matSolo [i,j] <- 1}
  }
}

在找到每行的值 1 后,我该如何break

有什么建议吗?

(期望矩阵)

      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
 [1,]    0    0    0    0    0    0    0    0    0     0     0
 [2,]    0    0    0    0    0    0    0    0    0     0     0
 [3,]    0    0    0    0    0    0    0    0    0     0     0
 [4,]    0    0    0    0    0    0    0    0    0     0     0
 [5,]    0    0    0    0    0    0    0    0    0     0     0
 [6,]    0    0    0    0    0    0    0    0    0     0     0
 [7,]    0    0    0    0    0    0    0    0    0     0     0
 [8,]    0    0    0    1    0    0    0    0    0     0     0
 [9,]    0    1    0    0    0    0    0    0    0     0     0
[10,]    0    0    0    0    0    0    0    0    0     0     0

【问题讨论】:

  • 使用which 并使用min 搜索每列的前1
  • @Roland - 我用预期的矩阵编辑了
  • 您应该使用整数,而不是数字,例如0L1L。它们占用的内存更少,使用起来更快。

标签: r loops matrix break


【解决方案1】:

你也可以试试

library(matrixStats)    
matSolo <- 1*(rowCumsums(SoloNight)==1)

【讨论】:

  • 我不知道matrixStats。 +1
【解决方案2】:

您似乎喜欢for 循环,而这些似乎是这里的自然选择。只需将您的代码更改为:

for(i in 1:nrow(matSolo)){
  for(j in 1:ncol(matSolo)){
    if(SoloNight[i,j] == 1) {
      matSolo [i,j] <- 1
      break
    }
  }
}

但是,对于大型矩阵,这将非常缓慢。幸运的是,它很容易翻译成 Rcpp:

library(Rcpp)
cppFunction(
'IntegerMatrix firstOne(const IntegerMatrix mat) {
  IntegerMatrix res(mat.nrow(), mat.ncol());
  for (int i=0; i<mat.nrow(); i++) {
    for (int j=0; j<mat.ncol(); j++) {
      if (mat(i,j) == 1) {
        res(i,j) = 1;
        break;
      }
    }
  }
  return res;
}
')

firstOne(SoloNight)

【讨论】:

  • 你指的是以前的问题吗?我确实喜欢loop - 它们帮助我思考(也让我的生活复杂化!)。感谢Rcpp - 非常好!
【解决方案3】:

你可以试试

 indx <- max.col(SoloNight, 'first')*(rowSums(SoloNight)!=0)
 matSolo[cbind(1:nrow(matSolo), indx) ] <- 1

基准测试

  set.seed(24)
  m1 <- matrix(sample(c(0,1), 5000*5000, replace=TRUE), ncol=5000)

  khashaa <- function(){
      matSolo <- rowCumsums(m1)
      matSolo[matSolo!=1] <- 0
       }
  khashaa2 <- function(){matSolo <- 1*(rowCumsums(m1)==1)}

  roland <- function() firstOne(m1)

  akrun <- function() {
       indx <- max.col(m1, 'first')*(rowSums(m1)!=0)
        matSolo <- m1*0
        matSolo[cbind(1:nrow(matSolo), indx) ] <- 1
       }

   system.time(akrun())
   #user  system elapsed 
   #0.349   0.044   0.395 
   system.time(roland())
   # user  system elapsed 
   # 0.144   0.021   0.166 
   system.time(khashaa())
   # user  system elapsed 
   # 0.555   0.055   0.611 
   system.time(khashaa2())
   # user  system elapsed 
   #0.265   0.054   0.319 

 library(microbenchmark)
 microbenchmark(akrun(), khashaa(),khashaa2(), roland(), unit='relative', times=20L)
 #Unit: relative
 #    expr      min       lq     mean   median       uq      max neval  cld
 # akrun() 2.383404 2.453934 2.298975 2.283178 2.304992 1.993665    20   c 
 #khashaa() 3.542353 3.601232 3.420879 3.429367 3.476025 2.898632    20    d
 #khashaa2() 1.900968 2.029436 1.909676 1.923457 1.948551 1.693583    20  b  
 # roland() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000    20 a   

【讨论】:

  • 非常非常非常好@akrun!
  • @giacomoV 是一种行/列索引方式。否则你可能需要applyPosition,这仍然会更慢。
  • 哦,我现在明白了 - 非常好。让我们看看是否有人有替代解决方案,然后我会接受你的答案。谢谢!
  • @giacomoV 在 5000*5000 矩阵上,system.time 上的 Rcpp 解决方案是 0.147,matrixStats 与 0.596 为一,base R0.348 索引
  • @Khashaa 我认为matrixStats 函数没有那么快。但是,你证明我错了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-30
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多