7

我需要抓住构成对称矩阵下三角形的所有三个元素三角形。我想不出如何按照最左边的列向下,然后是右边的下一列的顺序来抓取所有这些碎片,依此类推。我知道下三角形内的 numbe rof 迷你三角形是:

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 中以最快的方式完成这项任务?

不确定我所追求的这种视觉效果是否有帮助,但它可能是:

在此处输入图像描述

4

2 回答 2

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])
}
于 2012-12-07T04:35:57.143 回答
3

编辑添加一个SIMPLIFY=FALSE现在给出你想要的东西:

基本上,此方法获取所需三角形的所有左上角的索引,然后抓取 [cell below] + [cell below + to the right]。刺激。这种方法的另一个好处是它适用于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"
于 2012-12-07T05:08:36.917 回答