R编程:上一个/前一个/后续列的逻辑测试

时间:2016-03-21 10:17:20

标签: r matrix indexing comparison

我有一个名为'ft'的矩阵,这是一些逻辑测试的结果。 这是一个例子,[10,5]的矩阵。 在实际工作中,它将是数千行,更多列和大约数百个矩阵。

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

我需要对上一列的值进行逻辑测试。如果前一列的值为零,则列的其余部分将为零。 例如,向量[3,1]的值为零,因此行[3,]中的其余列将为零。同样,[10,2]中的元素为零,因此行[10,3:5]将为零 所以新矩阵的结果将是这样的:

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

我是R的新手,我尝试了以下几种替代方案:

ctes=cbind(ftes[,1], (ftes[,2:t]==1 & ctes[,-1]==1))

但这是完全错误的。 如何使用矢量化方法而不是循环测试有效地做到这一点。

2 个答案:

答案 0 :(得分:2)

我不认为base R提供了一种矢量化方法来解决这个问题,但如果效率很重要,你可以尝试使用matrixStats

matrixStats::rowCummins(ft)
#       [,1] [,2] [,3] [,4] [,5]
#  [1,]    1    1    1    1    1
#  [2,]    1    1    1    1    1
#  [3,]    0    0    0    0    0
#  [4,]    1    1    1    1    1
#  [5,]    1    1    1    1    1
#  [6,]    1    1    1    1    1
#  [7,]    1    1    1    1    1
#  [8,]    1    1    1    1    1
#  [9,]    1    1    1    1    1
# [10,]    1    0    0    0    0

200MB大小矩阵的基准

set.seed(123)
Bigft <- matrix(sample(0:1, 5e7, replace = TRUE), ncol = 100)
system.time(matrixStats::rowCummins(Bigft))
# user  system elapsed 
# 0.08    0.01    0.10 

答案 1 :(得分:1)

可能有一种更简单的方法,但这应该有效:

zeros <- which(ft==0,arr.ind=TRUE)
sapply(1:nrow(zeros), function(x) ft[zeros[x,1], zeros[x,2]:ncol(ft)] <<- 0)
#> ft
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    1    1    1    1
# [2,]    1    1    1    1    1
# [3,]    0    0    0    0    0
# [4,]    1    1    1    1    1
# [5,]    1    1    1    1    1
# [6,]    1    1    1    1    1
# [7,]    1    1    1    1    1
# [8,]    1    1    1    1    1
# [9,]    1    1    1    1    1
#[10,]    1    0    0    0    0

这不是矢量化的,但是循环仅在包含零的行上延伸,而不是整个矩阵。根据矩阵的密度,这可能会也可能不会产生巨大的差异。

数据

ft <- structure(c(1L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
      1L, 1L, 1L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
      1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
      1L, 1L, 1L, 1L, 1L), .Dim = c(10L, 5L), .Dimnames = list(NULL, NULL))