2011-04-19 70 views
5

我有對角線等於零和非對角線所有等於一(單位矩陣的倒數)的矩陣:創建整數的相似性矩陣,,使用R

mat1 <- matrix(c(0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0), 5, 5) 

我也有一個矢量這是永遠不變的長度爲基體的變暗,總是從零開始:使用這兩個對象,我想創建一個矩陣,看起來像這樣

vec1 <- c(0,1,2,3,4) 

mat2 <- matrix(c(0,1,2,3,4,1,0,1,2,3,2,1,0,1,2,3,2,1,0,1,4,3,2,1,0), 5, 5) 

    [,1] [,2] [,3] [,4] [,5] 
[1,] 0 1 2 3 4 
[2,] 1 0 1 2 3 
[3,] 2 1 0 1 2 
[4,] 3 2 1 0 1 
[5,] 4 3 2 1 0 

我想要一個將會泛化的操作,例如,如果我有一個9乘9的dims矩陣和一個0:8的向量,我可以獲得相同的結果。任何想法如何解決這個問題?

回答

6

由於VEC 1以零開始的,那麼你可以做:

MakeMatrix <- function(x){ 
    n <- length(x) 
    id <- abs(rep(1:n,n)-rep(1:n,each=n)) + 1 
    matrix(x[id],ncol=n) 
} 

MakeMatrix(vec1) 

所以沒有必要採取MAT1輸入,作爲一個實際上是多餘的。你可以在函數中構造矩陣。

訣竅在於提供一系列id值從矢量中進行選擇,然後將所有內容轉換爲矩陣。


編輯:如果你只打算使用序列,你還可做:

MakeMatrix <- function(n){ 
    id <- abs(rep(1:n,n)-rep(1:n,each=n)) 
    matrix(id,ncol=n) 
} 

MakeMatrix(7) 
+1

+1很好的使用代表。 – Andrie 2011-04-19 15:18:41

+0

我喜歡這種方法的簡單性。非常感謝! – Steve 2011-04-19 16:22:43

6

以下解決方案利用upper.trilower.tri來隔離上下三角矩陣。另外,它使用sequence來創建所需的矢量序列。

n <- 9 
vec <- (1:n)-1 
m <- matrix(0, n, n) 
m[lower.tri(m, diag=TRUE)] <- vec[sequence(n:1)] #### Edit 
m <- t(m) 
m[lower.tri(m, diag=TRUE)] <- vec[sequence(n:1)] #### Edit 
m 

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
[1,] 0 1 2 3 4 5 6 7 8 
[2,] 1 0 1 2 3 4 5 6 7 
[3,] 2 1 0 1 2 3 4 5 6 
[4,] 3 2 1 0 1 2 3 4 5 
[5,] 4 3 2 1 0 1 2 3 4 
[6,] 5 4 3 2 1 0 1 2 3 
[7,] 6 5 4 3 2 1 0 1 2 
[8,] 7 6 5 4 3 2 1 0 1 
[9,] 8 7 6 5 4 3 2 1 0 
+0

對於sequence和lower.tri()。不錯的一個,儘管你應該使用m作爲索引從輸入向量中進行選擇。沒有保證OP會使用vec1的序列... – 2011-04-19 15:18:38

+0

@Joris好評。我現在做了一個非常小的修改:使用sequence()作爲提供的向量的索引。這現在應該適用於任何n和vec。 – Andrie 2011-04-19 18:52:54

1

如何:

genMat <- function(n){ 
    mat <- outer(1:n,1:n,"-")%%n 
    tmp <- mat[lower.tri(mat)] 
    mat <- t(mat) 
    mat[lower.tri(mat)] <- tmp 
    mat 
} 

> genMat(5) 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 0 1 2 3 4 
[2,] 1 0 1 2 3 
[3,] 2 1 0 1 2 
[4,] 3 2 1 0 1 
[5,] 4 3 2 1 0 

編輯

對於任意vec1

genMat2 <- function(vec){ 
    n <- length(vec) 
    mat <- outer(1:n,1:n,"-")%%n 
    tmp <- mat[lower.tri(mat)] 
    mat <- t(mat) 
    mat[lower.tri(mat)] <- tmp 
    matrix(vec[mat+1],n,n) 
} 

> genMat2(c(0,2,4,3,9)) 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 0 2 4 3 9 
[2,] 2 0 2 4 3 
[3,] 4 2 0 2 4 
[4,] 3 4 2 0 2 
[5,] 9 3 4 2 0 

編輯2 其實,沒有必要使用模,然後用矩陣玩,abs將正常工作,使原來的矩陣定義1班輪:

abs(outer(1:n,1:n,"-")) 

所以,

genMat <- function(n){ 
    abs(outer(1:n,1:n,"-")) 
} 

genMat2 <- function(vec){ 
    n <- length(vec) 
    matrix(vec[abs(outer(1:n,1:n,"-"))+1],n,n) 
}