user3570187 user3570187 - 3 months ago 23
R Question

converting rows to columns to create a matrix

I have data in the following form and i would like to create a matrix from this data.

B<- c('nancy','bill','bob','badri','bill')
c<- c('martial-arts','dance','sports','judo','judo')

df<- data.frame(B,C)


I want to create a matrix who belongs to which group and with user as row.names. Can anyone have any suggestions?

user martial-arts dance sports judo
nancy 1 0 0 0
bill 0 1 0 1
bob 0 0 1 0
badri 0 0 0 1

Answer

Maybe something like this:

x <- c('nancy','bill','bob','badri','bill')
y <- c('martial-arts','dance','sports','judo','judo')

x0 <- unique(x); y0 <- unique(y)
mat <- matrix(0L, length(x0), length(y0), dimnames = list(x0, y0))
mat[cbind(match(x, x0), match(y, y0))] <- 1L

#      martial-arts dance sports judo
#nancy            1     0      0    0
#bill             0     1      0    1
#bob              0     0      1    0
#badri            0     0      0    1

I have used matrix indexing:

  • match(x, x0) gives row index;
  • match(y, y0) gives column index;
  • cbind(match(x, x0), match(y, y0)) gives matrix index where 1 is.

If you have an idea that the resulting matrix has a lot more zeros than ones, you may construct a sparse matrix:

library(Matrix)
sparseMatrix(i = match(x, x0), j = match(y, y0), x = 1, dimnames = list(x0, y0))

#4 x 4 sparse Matrix of class "dgCMatrix"
#      martial-arts dance sports judo
#nancy            1     .      .    .
#bill             .     1      .    1
#bob              .     .      1    .
#badri            .     .      .    1

I like @thelatemail's alternative:

xtabs(~ x + y)
xtabs(~ x + y, sparse = TRUE)