将矩阵从非正方形转换为具有不同列名的正方形

convert a matrix from non-square to square with different column names

我有一个矩阵

> dput(m1)
structure(c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 2L, 3L, 4L, 5L, 
6L, 7L, 8L, 9L, 4L, 5L, 6L), .Dim = 5:4, .Dimnames = list(c("A", 
"B", "C", "D", "E"), c("col1", "col2", "col3", "col4")))

我想通过添加填充有 1 的虚拟列或行(以缺少的为准)将我的矩阵转换为方形矩阵

我期望得到的:

structure(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 
4, 5, 6, 1, 1, 1, 1, 1), .Dim = c(5L, 5L), .Dimnames = list(c("A", 
"B", "C", "D", "E"), c("col1", "col2", "col3", "col4", "anyname")))
sqmat <- function(m) {
  while (ncol(m) < nrow(m)) {
    m <- cbind(m, anyname = 1)
  }
  while (nrow(m) < ncol(m)) {
    m <- rbind(m, anyname = 1)
  }
  return(m)
}

这可能会导致 row/column 名称重复,这可能是您不希望看到的。您可以跟踪索引并稍后重命名...

这里有一个函数可以帮助-

make_symmetric_matrix <- function(m) {
  nr <- nrow(m)
  nc <- ncol(m)
  if(nc > nr) {
    m <- rbind(m, matrix(1, nrow = nc - nr, nc = nc))
  } else if(nr > nc) {
    m <- cbind(m, matrix(1, nrow = nr, nc = nr - nc))
  }
  m
}

一些要检查的测试用例-

#on the original matrix
make_symmetric_matrix(m1)

#  col1 col2 col3 col4  
#A    1    6    3    8 1
#B    2    7    4    9 1
#C    3    8    5    4 1
#D    4    9    6    5 1
#E    5    2    7    6 1


test_mat <- matrix(c(1, 2, 3, 3, 4 ,5), ncol = 3)

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

make_symmetric_matrix(test_mat)
#     [,1] [,2] [,3]
#[1,]    1    3    4
#[2,]    2    3    5
#[3,]    1    1    1

test_mat <- matrix(c(1, 2, 3, 3, 4 ,5), ncol = 6)

#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    1    2    3    3    4    5

make_symmetric_matrix(test_mat)

#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    1    2    3    3    4    5
#[2,]    1    1    1    1    1    1
#[3,]    1    1    1    1    1    1
#[4,]    1    1    1    1    1    1
#[5,]    1    1    1    1    1    1
#[6,]    1    1    1    1    1    1

我们可以先重命名列名,然后

然后我们可以创建一个 NA 矩阵(在此处学习 要工作:此代码必须满足 akrun 在他的回答中陈述的假设!

然后使用 matrixcalc 包中的 is.square.matrix() 函数进行测试。

# Rename column names
colnames(m1) <- LETTERS[1:4]

# Use this code
un1 <- unique(sort(c(colnames(m1), rownames(m1))))
m2 <- matrix(NA, length(un1), length(un1), dimnames = list(un1, un1))
m2[row.names(m1), colnames(m1)] <- m1
m2

# Output:
  A B C D  E
A 1 6 3 8 NA
B 2 7 4 9 NA
C 3 8 5 4 NA
D 4 9 6 5 NA
E 5 2 7 6 NA

# Test if is a square matrix:
#install.packages("matrixcalc")
library(matrixcalc)
is.square.matrix(m2)

#Output:
[1] TRUE