EmilBB - 1 month ago 10
R Question

# how to select submatrix in a (adjacency) matrix based on ties, in R

I have a matrix, which represents mobility between various jobs:

jobdat <- matrix(c(
295, 20, 0, 0, 0, 5, 7,
45, 3309, 15, 0, 0, 0, 3,
23, 221, 2029, 5, 0, 0, 0,
0, 0, 10, 100, 8, 0, 3,
0, 0, 0, 0, 109, 4, 4,
0, 0, 0, 0, 4, 375, 38,
0, 18, 0, 0, 4, 26, 260),
nrow = 7, ncol = 7, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 3","job 4","job 5","job 6","job 7"),
c("job 1","job 2","job 3","job 4","job 5","job 6","job 7")))

This is treated as a directed, weighted adjacency matrix in a social network analysis.
The direction of the network is from rows to columns: So mobility is defined as going from a job-row to a job-column. The diagonal is meaningful, since it is possible to change to the same job in another firm.

For part of my analysis I want to select a submatrix which consists of job 1, job 5 and job 7:

work.list <- c(1,5,7)
jobpick_wrong <- jobdat[work.list,work.list]

however, this only gives the direct ties between these three jobs. What I need is this:

jobpick_right <- matrix(c(
295, 20, 0, 5, 7,
45, 3309, 0, 0, 3,
0, 0, 109, 4, 4,
0, 0, 4, 375, 38,
0, 18, 4, 26, 260),
nrow = 5, ncol = 5, byrow = TRUE,
dimnames = list(c("job 1","job 2","job 5","job 6","job 7"),
c("job 1","job 2","job 5","job 6","job 7")))

Here, job 2 and 6 are also included, since these two jobs also have direct ties to either job 1, 5 or 7. While job 3 and 4 are excluded, because they do not have any ties to job 1, 5 or 7.

I'm not sure how to go about this. Maybe I have to transform it into an igraph-object in order to get anywhere?

net <- graph.adjacency(jobdat, mode = "directed", weighted = TRUE)

and then maybe use the ego/neighborhood-function, also from the igraph package? But how I'm really not sure how. Or if this is the best way to go about it.

Emil Begtrup-Bright

Assuming your directed graph is from rows to columns, what you can do is to augment your work.list with those columns that are connected (with element !=0) to each row in the work.list. You can do this by:

work.list <- sort(unique(unlist(lapply(work.list, function(x) which(jobdat[x,] != 0)))))

Use unique to keep only the unique columns assembled and sort so that these columns are sorted by their indices. Then:

jobdat[work.list,work.list]
##      job 1 job 2 job 5 job 6 job 7
##job 1   295    20     0     5     7
##job 2    45  3309     0     0     3
##job 5     0     0   109     4     4
##job 6     0     0     4   375    38
##job 7     0    18     4    26   260