-2

I have a dataset of bilateral trade flows of dimension 84x244.

How can I balance the dataset to look like a 244x244 matrix but keeping the same order and names as the columns? Non-symmetric matrix

For example the matrix resembles: 
  A B C D
B 0 0 0 1
D 2 0 0 0

and it should look like 

  A B C D
A 0 0 0 0
B 0 0 0 1
C 0 0 0 0
D 2 0 0 0

With A B C D as row and column names 
  • Please make this question *reproducible*. This includes sample code (including listing non-base R packages), sample *unambiguous* data (e.g., `dput(head(x))` or `data.frame(x=...,y=...)`), and expected output. Refs: https://stackoverflow.com/questions/5963269, https://stackoverflow.com/help/mcve, and https://stackoverflow.com/tags/r/info. – r2evans Jan 13 '20 at 04:49
  • In this case ... perhaps give us a 3x8 matrix instead of 84x244, since if a general answer can do it with 8, it can likely scale to 244. – r2evans Jan 13 '20 at 04:51

2 Answers2

0

Here are two methods that ensure the column names and row names are effectively the same, using a default value of 0 for missing rows/columns. These do not assume that the columns are always full; if this is guaranteed, then you can ignore the column-adding portions.

Both start with:

m <- as.matrix(read.table(header=TRUE, text="
  A B C D
B 0 0 0 1
D 2 0 0 0"))

First

needrows <- setdiff(colnames(m), rownames(m))
m <- rbind(m, matrix(0, nrow=length(needrows), ncol=ncol(m), dimnames=list(needrows, colnames(m))))
needcols <- setdiff(rownames(m), colnames(m))
m <- cbind(m, matrix(0, nrow=nrow(m), ncol=length(needcols), dimnames=list(rownames(m), needcols)))
m
#   A B C D
# B 0 0 0 1
# D 2 0 0 0
# A 0 0 0 0
# C 0 0 0 0

And to order the rows same as the columns ... note that if there are row names not present in the column names, they will be removed in this, though you can include them with another setdiff if needed.

m[colnames(m),]
#   A B C D
# A 0 0 0 0
# B 0 0 0 1
# C 0 0 0 0
# D 2 0 0 0

Second

allnames <- sort(unique(unlist(dimnames(m))))
m2 <- matrix(0, nrow=length(allnames), ncol=length(allnames),
             dimnames=list(allnames, allnames))
m2[intersect(rownames(m), allnames), colnames(m)] <- 
  m[intersect(rownames(m), allnames), colnames(m)]
m2[rownames(m), intersect(colnames(m), allnames)] <- 
  m[rownames(m), intersect(colnames(m), allnames)]
m2
#   A B C D
# A 0 0 0 0
# B 0 0 0 1
# C 0 0 0 0
# D 2 0 0 0
r2evans
  • 141,215
  • 6
  • 77
  • 149
0

Here is a base R solution. The basic idea is that, you first construct a square matrix will all zeros and assign row names with its column names, and then assign value to the rows according to row names, i.e.,

M <- `dimnames<-`(matrix(0,nrow = ncol(m),ncol = ncol(m)),
                  replicate(2,list(colnames(m))))
M[rownames(m),] <- m

such that

> M
  A B C D
A 0 0 0 0
B 0 0 0 1
C 0 0 0 0
D 2 0 0 0
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81