R 编程:Previous/preceding/successive 列的逻辑测试
R Programming: Logical test of Previous/preceding/successive Column
我有一个名为 '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))
但这是完全错误的。
如何使用矢量化方法而不是循环测试有效地做到这一点。
可能有更简单的方法,但这应该可行:
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))
我不认为 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
我有一个名为 '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))
但这是完全错误的。 如何使用矢量化方法而不是循环测试有效地做到这一点。
可能有更简单的方法,但这应该可行:
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))
我不认为 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