在下三角形内抓取三角形

时间:2012-12-07 03:43:02

标签: r

我需要抓住组成对称矩阵下三角形的所有三个元素三角形。我想不出如何按照最左边的列向下工作顺序抓住所有这些部件然后向右下一列等等。我知道下三角形内部的数字迷你三角形是:

n = x(x - 1)/2
where: x = nrow(mats[[i]])

在这里,我创建了三个带字母的矩阵(这对我来说更容易概念化)以及我正在寻找的顺序中的元素:

FUN <- function(n) {
    matrix(LETTERS[1:(n*n)], n)
}

mats <- lapply(3:5, FUN)

因此,对于上面创建的每个矩阵,这是我想得到的输出(我把它放在代码而不是输出格式中):

list(c("B", "C", "F"))

list(c("B", "C", "G"), c("C", "D", "H"), c("G", "H", "L"))

list(c("B", "C", "H"), c("C", "D", "I"), c("D", "E", "J"), 
    c("H", "I", "N"), c("I", "J", "O"), c("N", "O", "T"))

如何在基地R停留期间以最快的方式完成此任务?

不确定我所追求的视觉是否有用,但可能是:

enter image description here

2 个答案:

答案 0 :(得分:5)

好的问题!以下是使用一点递归(后跟更简单的版本)来解决它的方法

triangle <- function(base.idx, mat) {
    upper.idx <- base.idx - 1L
    right.idx <- base.idx + nrow(mat)
    paste(mat[c(upper.idx, base.idx, right.idx)], collapse = " ")
}

get.triangles <- function(mat) {
    N <- nrow(mat)
    if (N == 3L) {
        return(triangle(3L, mat))
    } else {
        left.idx  <- 3:N
        right.mat <- mat[2:N, 2:N]
        left.triangles  <- sapply(left.idx, triangle, mat)
        right.triangles <- Recall(right.mat) 
        return(c(left.triangles, right.triangles))
    }
}

x <- lapply(mats, get.triangles)

# [[1]]
# [1] "B C F"
# 
# [[2]]
# [1] "B C G" "C D H" "G H L"
# 
# [[3]]
# [1] "B C H" "C D I" "D E J" "H I N" "I J O" "N O T"

我只是评论输出不完全按照你的要求。这是因为创建返回平面列表的递归函数总是难以使用:不知怎的,你总是以嵌套列表结束......

所以最后一步应该是:

lapply(x, strsplit, split = " ")

,它的格式与您要求的格式相同。


这是一个更简单的版本(忘记递归!)

get.triangles <- function(mat) {
    base.idx  <- seq_along(mat)[row(mat) > col(mat) + 1]
    upper.idx <- base.idx - 1L
    right.idx <- base.idx + nrow(mat)

    lapply(mapply(c, upper.idx, base.idx, right.idx, SIMPLIFY = FALSE),
           function(i)mat[i])
}

答案 1 :(得分:3)

编辑添加SIMPLIFY=FALSE,现在可以提供您想要的内容:

基本上,此方法获取所需三角形的所有左上角的索引,然后抓取[下方的单元格] + [下方+右侧的单元格]。快感。此方法的另一个好处是它适用于matrixdata.frame个对象。

bot.tris <- function(data) {
  idx1 <- unlist(sapply((nrow(data)-2):1,function(x) tail(2:(nrow(data)-1),x)))
  idx2 <- rep(1:(nrow(data)-2),(nrow(data)-2):1)
  mapply(function(x,y) {c(data[x,y],data[x+1,y],data[x+1,y+1])},idx1,idx2,SIMPLIFY=FALSE)
}

结果:

> result <- lapply(mats,bot.tris)
> str(result)
List of 3
 $ :List of 1
  ..$ : chr [1:3] "B" "C" "F"
 $ :List of 3
  ..$ : chr [1:3] "B" "C" "G"
  ..$ : chr [1:3] "C" "D" "H"
  ..$ : chr [1:3] "G" "H" "L"
 $ :List of 6
  ..$ : chr [1:3] "B" "C" "H"
  ..$ : chr [1:3] "C" "D" "I"
  ..$ : chr [1:3] "D" "E" "J"
  ..$ : chr [1:3] "H" "I" "N"
  ..$ : chr [1:3] "I" "J" "O"
  ..$ : chr [1:3] "N" "O" "T"