1

my problem at the moment is the following. I have a big list of matrices(about 1600). Actually it's adjencency matrices of cliques with varying size(from 2:2 to 5:5). here is example of 2 matrices

first

            name1      name2      name3
name1          1          1          1 
name2          1          1          1
name3          1          1          1

and second

           name4       name5      name6      name7
name4          1          1          1          1
name5          1          1          1          1
name6          1          1          1          1
name7          1          1          1          1

I need to merge this matrices into a bigger one and have something like that:

           name1    name2     name3     name4     name5     name6    name7
name1          1          1          1       0         0        0        0
name2          1          1          1       0         0        0        0
name3          1          1          1       0         0        0        0
name4          0          0          0       1         1        1        1
name5          0          0          0       1         1        1        1
name6          0          0          0       1         1        1        1
name7          0          0          0       1         1        1        1

But this is not all. If there are similar clique(like the first one for the example), or another one containing old names, i want its values to be summarized with the values in the big matrix. And get the matrix of following form:

           name1    name2     name3     name4     name5     name6    name7
name1          2          2          2       0         0        0        0
name2          2          2          2       0         0        0        0
name3          2          2          2       0         0        0        0
name4          0          0          0       1         1        1        1
name5          0          0          0       1         1        1        1
name6          0          0          0       1         1        1        1
name7          0          0          0       1         1        1        1

I will need these numbers to identify the power of links in my social network.

This problem seems very complicated for me, so i hope i described it clear enough for you :)

G.Lysov
  • 13
  • 3

2 Answers2

2

We create a matrix of 0's ('mN') with row names and column names from the union of row names and column names of the input matrices, with the dimensions from the length of the vectors ('rn/cn'). We place all the matrices in a list (lst), loop through the matrices, change the values of 'mN' that correspond to row/column index of the individual matrices to 1 and sum the corresponding list elements with Reduce.

lst <- list(m1, m2)
rn <- Reduce(union, lapply(lst, rownames))
cn <- Reduce(union, lapply(lst, colnames))
mN <- matrix(0, ncol=length(cn), nrow=length(rn), dimnames=list(rn, cn))

Reduce(`+`,lapply(lst, function(x) {mN[rownames(x), colnames(x)] <- 1; mN})) 
#      name1 name2 name3 name4 name5 name6 name7
#name1     1     1     1     0     0     0     0
#name2     1     1     1     0     0     0     0
#name3     1     1     1     0     0     0     0
#name4     0     0     0     1     1     1     1
#name5     0     0     0     1     1     1     1
#name6     0     0     0     1     1     1     1
#name7     0     0     0     1     1     1     1

If there are matching row/column names for more than one element, this would do the sum

lst <- list(m1, m2, m1)

and repeating the above steps

#      name1 name2 name3 name4 name5 name6 name7
#name1     2     2     2     0     0     0     0
#name2     2     2     2     0     0     0     0
#name3     2     2     2     0     0     0     0
#name4     0     0     0     1     1     1     1
#name5     0     0     0     1     1     1     1
#name6     0     0     0     1     1     1     1
#name7     0     0     0     1     1     1     1

data

m1 <- structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Dim = c(3L, 
3L), .Dimnames = list(c("name1", "name2", "name3"), c("name1", 
"name2", "name3")))

m2 <- structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L), .Dim = c(4L, 4L), .Dimnames = list(c("name4", "name5", 
"name6", "name7"), c("name4", "name5", "name6", "name7")))
akrun
  • 874,273
  • 37
  • 540
  • 662
1

Something like the following should do it:

# Toy data
m1 <- matrix(1, 4, 4, dimnames = list(paste0("name", 1:4), paste0("name", 1:4)))
m2 <- matrix(1, 5, 5, dimnames = list(paste0("name", 5:9), paste0("name", 5:9)))

# Create "your list"
mlist <- list(m1, m2, m1)

The strategy is to make a matrix with all the nodes/names and then add the cliques to this:

# Get all names
nms <- unique(unlist(lapply(mlist, colnames)))

# Create matrix to hold values
ans <- matrix(0, length(nms), length(nms), dimnames = list(nms, nms))

# Fill in values:
for (i in seq_along(mlist)) {
  n <- colnames(mlist[[i]])
  ans[n, n] <- ans[n, n] + mlist[[i]]
}
print(ans)
#      name1 name2 name3 name4 name5 name6 name7 name8 name9
#name1     2     2     2     2     0     0     0     0     0
#name2     2     2     2     2     0     0     0     0     0
#name3     2     2     2     2     0     0     0     0     0
#name4     2     2     2     2     0     0     0     0     0
#name5     0     0     0     0     1     1     1     1     1
#name6     0     0     0     0     1     1     1     1     1
#name7     0     0     0     0     1     1     1     1     1
#name8     0     0     0     0     1     1     1     1     1
#name9     0     0     0     0     1     1     1     1     1

This should also work for overlapping cliques.

EDIT The loop can be hidden away by something like:

ans <- matrix(0, length(nms), length(nms), dimnames = list(nms, nms))
lapply(mlist, function(m) {n <- rownames(m); ans[n,n] <<- ans[n,n] + m})
print(ans)
# .. as above ...

But, probably more R-ideomatic is the following:

ans <- matrix(0, length(nms), length(nms), dimnames = list(nms, nms))
tmp <- lapply(mlist, function(m) {ans[rownames(m),colnames(m)] <-  m; ans})
print(Reduce("+", tmp))
# .. as above ...

Using Reduce in a similar way as @akrun's answer.

Anders Ellern Bilgrau
  • 9,928
  • 1
  • 30
  • 37
  • Thank you, your method produces the same matrix as @akrun's one. This fact allows me to feel completely confident about the produced data – G.Lysov Sep 28 '15 at 14:49