2

My trial data is given as follows:

testdata = matrix(c(1,1,1,2,2,3,3,3,10,11,12,13,
14,15,16,17,28,30,25,40,50,47,62,23),ncol=3,byrow=F)
colnames(testdata)=c("index","contact","age")

testdata
#>      index contact age
#> [1,]     1      10  28
#> [2,]     1      11  30
#> [3,]     1      12  25
#> [4,]     2      13  40
#> [5,]     2      14  50
#> [6,]     3      15  47
#> [7,]     3      16  62
#> [8,]     3      17  23

From the given data, I want create a matrix similar to an adjacency matrix as follows.

adjmat = matrix(c(0,0,0,28,30,25,rep(0,11),40,50,
rep(0,11),47,62,23,28, rep(0,10),30,rep(0,10),25, rep(0,11), 40, rep(0,10),50, 
rep(0,11),47, rep(0,10), 62,rep(0,10), 23, rep(0,8)),ncol=11,byrow=T,     
dimnames = list(c("1", "2","3","10","11","12","13","14","15","16","17"),
c("1","2","3","10","11","12","13","14","15","16","17")))

That means in matrix form it will be as follows:

adjmat
#>     1  2  3 10 11 12 13 14 15 16 17
#> 1   0  0  0 28 30 25  0  0  0  0  0
#> 2   0  0  0  0  0  0 40 45  0  0  0
#> 3   0  0  0  0  0  0  0  0 47 62 23
#> 10 28  0  0  0  0  0  0  0  0  0  0
#> 11 30  0  0  0  0  0  0  0  0  0  0
#> 12 25  0  0  0  0  0  0  0  0  0  0
#> 13  0 40  0  0  0  0  0  0  0  0  0
#> 14  0 50  0  0  0  0  0  0  0  0  0
#> 15  0  0 47  0  0  0  0  0  0  0  0
#> 16  0  0 62  0  0  0  0  0  0  0  0
#> 17  0  0 23  0  0  0  0  0  0  0  0

How can I do that? I tried with the following for loop, but it was not successful as expected.

index=c(1,1,1,2,2,3,3,3)
   contact=c(10,11,12,13,14,15,16,17)
   age=c(28,30,25,40,50,47,62,23)
   row=c(1,2,3,10,11,12,13,14,15,16,17)
   col=c(1,2,3,10,11,12,13,14,15,16,17)
   x=matrix(, nrow=11, ncol=11)

 for (i in 1:length(row)){
     for (j in 1:length(col)){
       for (k in 1:length(index)){
          for (m in 1:length(contact)){
   if(index[k]==row[i] & contact[m]==col[j]) {x[i,j]<- age[k]}
          else {x[i,j]<- 0}   
   print(x)   
     }}}}
Eric Fail
  • 8,191
  • 8
  • 72
  • 128
  • How did you know the code you wrote is not working? It gives an error (please share the error message) or the result doesn't match the expectation? (please share the result) – David Lay Feb 12 '18 at 19:10
  • Dear David, Thanks for your reply. I think some other friends already showed the way to solve. – Lutfor Rahman Feb 13 '18 at 12:14

4 Answers4

1

I've had that exact problem a few weeks back and ended up writing and adding a function for exactly that in the networkR package.

The adjacency function takes three vectors representing from, to, and weight which correspond to your three columns. The argument directed=FALSE is set to make the output symmetric.

library(networkR)
testdata = matrix(c(1,1,1,2,2,3,3,3,10,11,12,13,
                    14,15,16,17,28,30,25,40,50,47,62,23),ncol=3,byrow=F)

result <- adjacency(from=testdata[,1], 
                    to=testdata[,2], 
                    weight=testdata[,3], directed=FALSE)

result

which returns a sparse matrix with the following output.

11 x 11 sparse Matrix of class "dsCMatrix"

 [1,]  .  .  . 28 30 25  .  .  .  .  .
 [2,]  .  .  .  .  .  . 40 50  .  .  .
 [3,]  .  .  .  .  .  .  .  . 47 62 23
 [4,] 28  .  .  .  .  .  .  .  .  .  .
 [5,] 30  .  .  .  .  .  .  .  .  .  .
 [6,] 25  .  .  .  .  .  .  .  .  .  .
 [7,]  . 40  .  .  .  .  .  .  .  .  .
 [8,]  . 50  .  .  .  .  .  .  .  .  .
 [9,]  .  . 47  .  .  .  .  .  .  .  .
[10,]  .  . 62  .  .  .  .  .  .  .  .
[11,]  .  . 23  .  .  .  .  .  .  .  .
ekstroem
  • 5,957
  • 3
  • 22
  • 48
1

Base R solution will be something like:

> x<-unique(sort(testdata[,1:2]))
> m=matrix(0,length(x),length(x),dimnames = list(x,x))
> m[cbind(testdata[,1],which(x%in%testdata[,2]))]=testdata[,3]
> m[lower.tri(m)]=t(m)[lower.tri(m)]
> m
    1  2  3 10 11 12 13 14 15 16 17
1   0  0  0 28 30 25  0  0  0  0  0
2   0  0  0  0  0  0 40 50  0  0  0
3   0  0  0  0  0  0  0  0 47 62 23
10 28  0  0  0  0  0  0  0  0  0  0
11 30  0  0  0  0  0  0  0  0  0  0
12 25  0  0  0  0  0  0  0  0  0  0
13  0 40  0  0  0  0  0  0  0  0  0
14  0 50  0  0  0  0  0  0  0  0  0
15  0  0 47  0  0  0  0  0  0  0  0
16  0  0 62  0  0  0  0  0  0  0  0
17  0  0 23  0  0  0  0  0  0  0  0
Onyambu
  • 67,392
  • 3
  • 24
  • 53
1

if you you are willing to use the package it can be done relatively easily,

# install.packages(c("igraph"), dependencies = T)
require(igraph)
g <- graph.data.frame(testdata, directed=F, vertices=NULL)
m <- as_adjacency_matrix(g, attr = "age", sparse = F)
identical(m, adjmat)
#> [1] TRUE
m
#>     1  2  3 10 11 12 13 14 15 16 17
#> 1   0  0  0 28 30 25  0  0  0  0  0
#> 2   0  0  0  0  0  0 40 50  0  0  0
#> 3   0  0  0  0  0  0  0  0 47 62 23
#> 10 28  0  0  0  0  0  0  0  0  0  0
#> 11 30  0  0  0  0  0  0  0  0  0  0
#> 12 25  0  0  0  0  0  0  0  0  0  0
#> 13  0 40  0  0  0  0  0  0  0  0  0
#> 14  0 50  0  0  0  0  0  0  0  0  0
#> 15  0  0 47  0  0  0  0  0  0  0  0
#> 16  0  0 62  0  0  0  0  0  0  0  0
#> 17  0  0 23  0  0  0  0  0  0  0  0
Eric Fail
  • 8,191
  • 8
  • 72
  • 128
  • Dear Eric, Many thanks for one of the best solutions. I know how to use igraph package, but could not find a way to implement this way! thanks for kind help again. – Lutfor Rahman Feb 13 '18 at 12:31
  • Glad it was useful. Don't forget to mark your preferred answer as _accept_. [Here's how](https://stackoverflow.com/help/someone-answers). – Eric Fail Feb 13 '18 at 12:41
0

The function @ekstroem developed is probably more flexible, but you do not need any loops to create the matrix:

testdata <- matrix(c(1,1,1,2,2,3,3,3,10,11,12,13,
    14,15,16,17,28,30,25,40,50,47,62,23), ncol=3, 
    byrow=FALSE)
colnames(testdata)=c("index","contact","age")

rc <- unique(c(testdata[, 1:2]))
adjmat <- matrix(0, length(rc), length(rc), dimnames=list(rc, rc))
idx1 <- match(testdata[, 1], rc)
idx2 <- match(testdata[, 2], rc)
adjmat[cbind(idx1, idx2)] <- testdata[, 3]
adjmat[cbind(idx2, idx1)] <- testdata[, 3]
adjmat

Gives you the following result:

    1  2  3 10 11 12 13 14 15 16 17
1   0  0  0 28 30 25  0  0  0  0  0
2   0  0  0  0  0  0 40 50  0  0  0
3   0  0  0  0  0  0  0  0 47 62 23
10 28  0  0  0  0  0  0  0  0  0  0
11 30  0  0  0  0  0  0  0  0  0  0
12 25  0  0  0  0  0  0  0  0  0  0
13  0 40  0  0  0  0  0  0  0  0  0
14  0 50  0  0  0  0  0  0  0  0  0
15  0  0 47  0  0  0  0  0  0  0  0
16  0  0 62  0  0  0  0  0  0  0  0
17  0  0 23  0  0  0  0  0  0  0  0
dcarlson
  • 10,936
  • 2
  • 15
  • 18