7

対称行列の下の三角形を構成する3つの要素の三角形すべてを取得する必要があります。左端の列が下に向かって、次に右の列が下に行くという順序で、これらすべてのピースを取得する方法を考えることはできません。下の三角形の内側にあるnumberofミニ三角形は次のとおりです。

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

ここでは、文字(この方法で概念化する方が簡単です)と、探している順序の要素を使用して3つのマトリックスを作成しました。

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。これにより、必要なものが正確に提供されます。

基本的に、このメソッドは、必要な三角形の左上隅すべてのインデックスを取得してから、[下のセル]+[下のセル+右]を取得します。スリル。このメソッドの追加の利点の1つは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 に答える