vivek
vivek

Reputation: 311

Better way to create edge list matrix using an adjacency matrix

I have a matrix as follows: (adjacency matrix)

   R S K
A 1 1 0
B 0 1 0
C 1 0 0
D 1 0 0
E 0 0 1
F 0 0 1

The objective is to get a square matrix, which will have dimension as number of rows and columns in the above matrix. This matrix would be filled using the above matrix (if A-S is 1, then S-A should be also 1) and the results should look like this (edge-list matrix),

 A B C D E F R S K
A 0 0 0 0 0 0 1 1 0
B 0 0 0 0 0 0 0 1 0
C 0 0 0 0 0 0 1 0 0
D 0 0 0 0 0 0 1 0 0
E 0 0 0 0 0 0 0 0 1
F 0 0 0 0 0 0 0 0 1
R 1 0 1 1 0 0 0 0 0
S 1 1 0 0 0 0 0 0 0
K 0 0 0 0 1 1 0 0 0

I have written the following code which works well, I was wondering if there is an efficient way to achieve the above result?

#READ THE FIRST DATA FRAME
df <- read.table(text = "R S K
1      1     0
0      1     0
1      0     0
1      0     0
0      0     1
0      0     1", header=TRUE)

#INPUT THE ROW NAMES IN df
rownames(df)<-LETTERS[1:6]
#INITIALIZE A SQUARE MATRIX WITH #ROWS=#COLUMNS=#(ROWS OF df)+#(COLUMNS OF df)
godmat<-matrix(0, nrow =  sum(dim(df)), ncol= sum(dim(df)))
# ASSING ROW AND COLUMN NAMES
rownames(godmat) <- c(rownames(df),colnames(df))
colnames(godmat)  <- c(rownames(df),colnames(df))

#fill the matrix using df
for (i in colnames(godmat))
  for (j in colnames(godmat)) {
    godmat[i,j]=tryCatch({ godmat[i,j]<-df[which(rownames(df)==i), which(colnames(df)==j)]}, error = function(cond) { return(0)})
    #godmat[j,i]=godmat[i,j]
  }

#fill the matrix using df by copying the elements already filled
for (i in colnames(godmat))
  for (j in colnames(godmat)) {
   godmat[j,i]=godmat[i,j]
  }

Upvotes: 2

Views: 428

Answers (2)

989
989

Reputation: 12935

You could do this using merge and rbind and cbind in base R:

nm <- rownames(df)
m <- matrix(0,nrow(df),nrow(df),dimnames = list(nm,nm))
p1 <- merge(m, df, by = "row.names")[-1]
p2 <- cbind(t(df),matrix(0,ncol(df),ncol(df),dimnames = list(names(df),NULL)))
colnames(p2) <- c(nm, names(df))
res <- rbind(p1,p2)
rownames(res) <- c(nm, names(df))

 # A B C D E F R S K
# A 0 0 0 0 0 0 1 1 0
# B 0 0 0 0 0 0 0 1 0
# C 0 0 0 0 0 0 1 0 0
# D 0 0 0 0 0 0 1 0 0
# E 0 0 0 0 0 0 0 0 1
# F 0 0 0 0 0 0 0 0 1
# R 1 0 1 1 0 0 0 0 0
# S 1 1 0 0 0 0 0 0 0
# K 0 0 0 0 1 1 0 0 0

p1 is where adjacency matrix is attached column-wise. p2 is the row-wise one and then rbind(p1,p2). These two are the main parts. The rest are just setting the names.

Upvotes: 0

akrun
akrun

Reputation: 887711

We create a matrix of 0's based on the length of unique dimnames of the first dataset. Based on the match between the rownames and colnames of both the datasets, we assign the values of 'm1' to 'm2', take the transpose and add it with 'm2'

un1 <- unique(unlist(dimnames(m1)))
m2 <- matrix(0, length(un1), length(un1), dimnames = list(un1, un1))
i1 <- match(rownames(m1), rownames(m2), nomatch =0)
j1 <- match(colnames(m1), rownames(m2), nomatch = 0)
m2[i1, j1] <- m1
t(m2)+m2
#  A B C D E F R S K
#A 0 0 0 0 0 0 1 1 0
#B 0 0 0 0 0 0 0 1 0
#C 0 0 0 0 0 0 1 0 0
#D 0 0 0 0 0 0 1 0 0
#E 0 0 0 0 0 0 0 0 1
#F 0 0 0 0 0 0 0 0 1
#R 1 0 1 1 0 0 0 0 0
#S 1 1 0 0 0 0 0 0 0
#K 0 0 0 0 1 1 0 0 0

Upvotes: 1

Related Questions