GOGA GOGA
GOGA GOGA

Reputation: 407

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

I have a matrix

> 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")))

I want to convert my matrix to a square one by adding dummy columns or rows (whichever is missing) that are filled with 1

What I expect to get:

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")))

Upvotes: 1

Views: 647

Answers (3)

TarJae
TarJae

Reputation: 78927

We could first rename the column names and

then we could create a NA matrix (learned here How to convert a non-square matrix to a square matrix with R? To work: this code must fulfill the assumptions stated by akrun in his answer!

then test with is.square.matrix() function from matrixcalc package.

# 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

Upvotes: 3

Ronak Shah
Ronak Shah

Reputation: 388982

Here is a function that can help -

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
}

Some test cases to check -

#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

Upvotes: 4

Ben Bolker
Ben Bolker

Reputation: 226192

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)
}

This could lead to duplicate row/column names, which you might not want. You could keep track of an index and rename later ...

Upvotes: 4

Related Questions