2015-01-14 13 views
15

行列のすべての対角線を取得する方法を理解しようとしています。 は、例えば、私は、次の行列を持っていると言う: < - マトリックス(1:16,4)diag(A)関数を用い行列からすべての対角ベクトルを取得する

私はたい、主要対角線に加え

[1] 1 6 11 16 

が返されその上下のすべての対角線のリスト

5 10 15 
2 7 12 
9 14 
3 8 
4 
13 

私は、しかし、私は任意のサイズの行列のためにそれらの残りの部分を取得するためにコードを拡張する方法を見つけ出すように見えることはできません、私に直接プライマリー1以上と以下の対角線を与える次のリンクhttps://stackoverflow.com/a/13049722を発見しました。私は2つのネストされたforループを試しました。なぜなら、いくつかの種類の行列添え字が、私が探している結果を生成するように見えるからです。 forループでncol(A)、nrow(A)を使ってみましたが、正しい組み合わせを見つけることができませんでした。

2本の対角線を返さ
diag(A[-4,-1]) 
diag(A[-1,-4]) 

、もちろん

上下両方これは正方形である:プラス私は、ループは、一般的にR.

に眉をひそめているために与えられたコードがあったことを認識していますこれを実行したい行列のすべてが正方形ではないことに注意してください。必要であれば、非正方形領域にNAsを充填することも許容される。私が必要とする回答は、ページ上の他の回答の1つにあるかもしれませんが、元の質問には手段、合計などが含まれています。私はこれに対する解決策がばかげて簡単だと感じていますが、それは私には起こりません。私はまた、私はどこでもこの質問を見つけることができなかったことに驚いています、それは十分な共通の質問であるようです。たぶん私はこの問題の適切な用語を知らないかもしれません。

+0

なぜ@ GavinSimpsonの答えはありませんか? – A5C1D2H2I1M1N2O1R2T1

+0

私はこの答えも読んだので、解決策は行と列の数に基づいてインクリメントすることを理解していますが、これを1つの行列のすべての対角線を返す関数としてパッケージ化する方法は、私はすべての答えを繰り返し読んだ。 – Beaker

+4

サイドノート: 'for 'ループはぼやけていません。それは神話です(IMO)。それらはすべてソースコードの上にあります。他の機能と同様に、適切に使用する必要があります。 :-) –

答えて

46
A <- matrix(1:16, 4) 

# create an indicator for all diagonals in the matrix 
d <- row(A) - col(A) 

# use split to group on these values 
split(A, d) 

# 
# $`-3` 
# [1] 13 
# 
# $`-2` 
# [1] 9 14 
# 
# $`-1` 
# [1] 5 10 15 
# 
# $`0` 
# [1] 1 6 11 16 
# 
# $`1` 
# [1] 2 7 12 
# 
# $`2` 
# [1] 3 8 
# 
# $`3` 
# [1] 4 
+6

すばらしい。あなたは勝ちます(+1) –

+5

すごいくそ!そりゃ素晴らしい!非正方行列でも正しく動作するように見えます。 – Beaker

+5

であり、逆対角線 '行(A)+ col(A)'のために変更することができます – user20650

4

正方形の行列を扱っているので、Gavinの答えをオフセット値として使用する範囲を最初に計算する小さな関数に変換するのは本当に簡単です。このような関数は次のとおりです。

AllDiags <- function(inmat, sorted = TRUE) { 
    Range <- ncol(inmat) - 1 
    Range <- -Range:Range 
    if (isTRUE(sorted)) Range <- Range[order(abs(Range))] 
    lapply(Range, function(x) { 
    inmat[row(inmat) == (col(inmat) - x)] 
    }) 
} 

ここでは、サンプル行列 "A"の出力を示します。

AllDiags(A) 
# [[1]] 
# [1] 1 6 11 16 
# 
# [[2]] 
# [1] 2 7 12 
# 
# [[3]] 
# [1] 5 10 15 
# 
# [[4]] 
# [1] 3 8 
# 
# [[5]] 
# [1] 9 14 
# 
# [[6]] 
# [1] 4 
# 
# [[7]] 
# [1] 13 
3

ここでは、行列を縮小し、拡大することにより、すべての対角線を得ることができ、観測に基づいて一つの解決策です。まず、行N col 1(そのdiag取得)、次に行(N-1):およびcols(1:2)を検討します。それの対角を取得します。

N <- ncol(A) 
rows <- cbind(c(N:1, rep(1,N-1)), c(rep(N,N), (N-1):1)) # row indeces 
cols <- apply(rows, 2, rev)        # col indeces 

diagMatSubset <- function(mat, i1, i2, j1, j2) diag(mat[i1:i2, j1:j2, drop=FALSE]) 

Map(diagMatSubset, list(A), rows[,1], rows[,2], cols[,1], cols[,2]) 

[[1]] 
[1] 4 

[[2]] 
[1] 3 8 

[[3]] 
[1] 2 7 12 

[[4]] 
[1] 1 6 11 16 

[[5]] 
[1] 5 10 15 

[[6]] 
[1] 9 14 

[[7]] 
[1] 13 
関連する問題