试图找出 15x15 二进制矩阵中每个 3x3 块中 1 的对角线数量?
Trying to find the number of diagonals of 1 in each 3x3 tile in a 15x15 binary matrix?
我试图找出每个 3x3 方块中对角线 1 的数量,例如
0 0 1 1 0 0
0 1 0 0 1 0
1 0 0 or 0 0 1
来自下面的 15x15 矩阵。
set.seed(99)
mat <- matrix(sample(c(0,1), 225, prob=c(0.8,0.2), replace=TRUE), nrow=15)
print(mat)
[,1][,2][,3][,4][,5][,6][,7][,8][,9][,10][,11][,12][,13][,14][,15]
[1,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
[2,] 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1
[3,] 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0
[4,] 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1
[5,] 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0
[6,] 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0
[7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[8,] 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0
[9,] 0 0 0 0 0 1 0 0 1 1 0 0 1 0 1
[10,] 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0
[11,] 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0
[12,] 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0
[13,] 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0
[14,] 1 1 0 1 1 0 0 0 0 1 0 0 0 0 1
[15,] 1 0 1 0 1 1 0 0 0 1 0 1 0 0 0
我希望上述矩阵的输出为 2。有没有办法用 for 循环和 if 语句来做到这一点?
我们可以使用 outer()
。为此,我们编写了两个小的向量化函数,用于计算矩阵的 3x3 切片的对角线元素;如果 sum
是 3
我们有一个有效的对角线。
我们从 .
借用了代码的反对角线
counterdiag <- function(M) M[(n<-nrow(M))^2-(1:n)*(n-1)]
现在我们只需要一些坐标。
m <- n <- mapply(function(i) i:(i+2), 1:13)
还有我们的计数功能。
fun1 <- Vectorize(function(x, y) sum(diag(mat[m[,x], n[,y]])) == 3, SIMPLIFY=FALSE)
fun2 <- Vectorize(function(x, y) sum(counterdiag(mat[m[,x], n[,y]])) == 3, SIMPLIFY=FALSE)
用法
sum(unlist(outer(1:13, 1:13, fun1))) # diagonals
# [1] 1
sum(unlist(outer(1:13, 1:13, fun2))) # counterdiagonals
# [1] 3
这是一个嵌套的 for 循环(使用 sapply()
)。请注意,我没有与您相同的数据集,因此有不同的种子。
set.seed(123)
mat <- matrix(sample(c(0,1), 225, prob=c(0.8,0.2), replace=TRUE), nrow=15)
n_by_n <- 3L
reg_diag <- diag(n_by_n)
rev_diag <- reg_diag[nrow(reg_diag):1, ]
sum(
sapply(seq_len(ncol(mat)- n_by_n + 1),
function(col) {
sapply(seq_len(nrow(mat) - n_by_n + 1),
function(row) {
tmp <- mat[row:(row + n_by_n - 1), col:(col + n_by_n - 1)]
all(tmp == reg_diag) | all(tmp == rev_diag)
})
})
)
#[1] 1
如果您只对对角线感兴趣而不关心子矩阵中的其他值,这会将矩阵按每个对角线拆分,然后计算滚动总和以查看它们总和是否为 3:
library(RcppRoll)
set.seed(99)
mat <- matrix(sample(c(0,1), 225, prob=c(0.8,0.2), replace=TRUE), nrow=15)
n_by_n <- 3
diags <- row(mat)- col(mat)
cross_diags <- row(mat) + col(mat)
#could use data.table::frollsum instead of RcppRoll::roll_sumr)
sum(unlist(lapply(split(mat, diags), RcppRoll::roll_sumr, n_by_n), use.names = F) == n_by_n, na.rm = T)
#[1] 1
sum(unlist(lapply(split(mat, cross_diags), RcppRoll::roll_sumr, n_by_n), use.names = F) == n_by_n, na.rm = T)
# [1] 3
一个完整的基本方法是:
base_rollr <- function(x, roll) {
#from user @flodel
if (length(x) >= roll) tail(cumsum(x) - cumsum(c(rep(0, roll), head(x, -roll))), -roll + 1)
}
sum(unlist(lapply(split(mat, cross_diags), base_rollr, n_by_n), use.names = F) == n_by_n, na.rm = T)
另请参阅:
并且:
Consecutive/Rolling sums in a vector in R
我试图找出每个 3x3 方块中对角线 1 的数量,例如
0 0 1 1 0 0
0 1 0 0 1 0
1 0 0 or 0 0 1
来自下面的 15x15 矩阵。
set.seed(99)
mat <- matrix(sample(c(0,1), 225, prob=c(0.8,0.2), replace=TRUE), nrow=15)
print(mat)
[,1][,2][,3][,4][,5][,6][,7][,8][,9][,10][,11][,12][,13][,14][,15]
[1,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
[2,] 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1
[3,] 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0
[4,] 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1
[5,] 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0
[6,] 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0
[7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[8,] 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0
[9,] 0 0 0 0 0 1 0 0 1 1 0 0 1 0 1
[10,] 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0
[11,] 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0
[12,] 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0
[13,] 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0
[14,] 1 1 0 1 1 0 0 0 0 1 0 0 0 0 1
[15,] 1 0 1 0 1 1 0 0 0 1 0 1 0 0 0
我希望上述矩阵的输出为 2。有没有办法用 for 循环和 if 语句来做到这一点?
我们可以使用 outer()
。为此,我们编写了两个小的向量化函数,用于计算矩阵的 3x3 切片的对角线元素;如果 sum
是 3
我们有一个有效的对角线。
我们从
counterdiag <- function(M) M[(n<-nrow(M))^2-(1:n)*(n-1)]
现在我们只需要一些坐标。
m <- n <- mapply(function(i) i:(i+2), 1:13)
还有我们的计数功能。
fun1 <- Vectorize(function(x, y) sum(diag(mat[m[,x], n[,y]])) == 3, SIMPLIFY=FALSE)
fun2 <- Vectorize(function(x, y) sum(counterdiag(mat[m[,x], n[,y]])) == 3, SIMPLIFY=FALSE)
用法
sum(unlist(outer(1:13, 1:13, fun1))) # diagonals
# [1] 1
sum(unlist(outer(1:13, 1:13, fun2))) # counterdiagonals
# [1] 3
这是一个嵌套的 for 循环(使用 sapply()
)。请注意,我没有与您相同的数据集,因此有不同的种子。
set.seed(123)
mat <- matrix(sample(c(0,1), 225, prob=c(0.8,0.2), replace=TRUE), nrow=15)
n_by_n <- 3L
reg_diag <- diag(n_by_n)
rev_diag <- reg_diag[nrow(reg_diag):1, ]
sum(
sapply(seq_len(ncol(mat)- n_by_n + 1),
function(col) {
sapply(seq_len(nrow(mat) - n_by_n + 1),
function(row) {
tmp <- mat[row:(row + n_by_n - 1), col:(col + n_by_n - 1)]
all(tmp == reg_diag) | all(tmp == rev_diag)
})
})
)
#[1] 1
如果您只对对角线感兴趣而不关心子矩阵中的其他值,这会将矩阵按每个对角线拆分,然后计算滚动总和以查看它们总和是否为 3:
library(RcppRoll)
set.seed(99)
mat <- matrix(sample(c(0,1), 225, prob=c(0.8,0.2), replace=TRUE), nrow=15)
n_by_n <- 3
diags <- row(mat)- col(mat)
cross_diags <- row(mat) + col(mat)
#could use data.table::frollsum instead of RcppRoll::roll_sumr)
sum(unlist(lapply(split(mat, diags), RcppRoll::roll_sumr, n_by_n), use.names = F) == n_by_n, na.rm = T)
#[1] 1
sum(unlist(lapply(split(mat, cross_diags), RcppRoll::roll_sumr, n_by_n), use.names = F) == n_by_n, na.rm = T)
# [1] 3
一个完整的基本方法是:
base_rollr <- function(x, roll) {
#from user @flodel
if (length(x) >= roll) tail(cumsum(x) - cumsum(c(rep(0, roll), head(x, -roll))), -roll + 1)
}
sum(unlist(lapply(split(mat, cross_diags), base_rollr, n_by_n), use.names = F) == n_by_n, na.rm = T)
另请参阅:
并且: Consecutive/Rolling sums in a vector in R