简体   繁体   中英

How to create a matrix with 1s and 0s based off a 2-column data frame

Here is an example of what my data looks like (what I have is actually 1300 lines, or 1300 connections/edges between two different nodes):

node# node#
1  3
1  4
2  4
2  5
3  4
3  5

I currently have the above data in a data frame. This represent a network where a car can drive from node 1 to 3 or 1 to 4, and from node 2 to 4 or node 2 to 5, etc. I'd like to create a matrix that looks like this:

>      [,1] [,2] [,3] [,4] [,5] [,6]
 [1,]    0    0    0    0    0    0
 [2,]    0    0    0    0    0    0
 [3,]    0    0    0    0    0    0
 [4,]    0    0    0    0    0    0
 [5,]    0    0    0    0    0    0

Where I'm stuck: I want to input 1s into the matrix from the leaving node, and a -1 in the matrix of the destination node, in the same column. So for this 6 node-connection data frame, the matrix would look like:

>      [,1] [,2] [,3] [,4] [,5] [,6]
 [1,]    1    1    0    0    0    0
 [2,]    0    0    1    1    0    0
 [3,]   -1    0    0    0    1    1
 [4,]    0   -1   -1    0   -1    0
 [5,]    0    0    0   -1    0   -1

But like I said, I have more than 1300 connections, so doing this by hand would take a while. So I'm guessing matrix(0, 5, 1300) would be where I start?

You can index specific row/column pairs of a matrix using a 2-column indexing matrix. This provides a convenient way to set all the 1's and then set all the -1's:

mat <- matrix(0, nrow=max(dat), ncol=nrow(dat))
mat[cbind(dat$node1, seq_len(nrow(dat)))] <- 1
mat[cbind(dat$node2, seq_len(nrow(dat)))] <- -1
mat
#      [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]    1    1    0    0    0    0
# [2,]    0    0    1    1    0    0
# [3,]   -1    0    0    0    1    1
# [4,]    0   -1   -1    0   -1    0
# [5,]    0    0    0   -1    0   -1

(Thanks to @PierreLafortune for the trick about calling max on a data frame!)

Data:

dat <- data.frame(node1=c(1, 1, 2, 2, 3, 3), node2=c(3, 4, 4, 5, 4, 5))

We could also use sparseMatrix from library(Matrix)

library(Matrix)
B <- sparseMatrix(dat$node2, seq_len(nrow(dat)), x= -1)
mat <- sparseMatrix(dat$node1, seq_len(nrow(dat)), x= 1,
                      dims=dim(B)) + B
as.matrix(mat)
#      [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    1    1    0    0    0    0
#[2,]    0    0    1    1    0    0
#[3,]   -1    0    0    0    1    1
#[4,]    0   -1   -1    0   -1    0
#[5,]    0    0    0   -1    0   -1

NOTE: dat taken from @josliber's post.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM