Outlier
Outlier

Reputation: 437

How to re-structure a matrix in R?

Suppose I have a 5 x 5 matrix in R as follows:

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

I would like to re-format this matrix into the following structure:

For each row, list the row number and every associated column index containing element 1. For example, if we use the matrix above, we get:

1, 2, 3, 5

2, 1, 4

3, 4

4, 1, 3, 5

5, 1

Upvotes: 2

Views: 110

Answers (3)

akrun
akrun

Reputation: 887108

An option is split

with(as.data.frame(which(m == 1, arr.ind = TRUE)), split(col, row))
#$`1`
#[1] 1 2 4 5

#$`2`
#[1] 1 2 3 4

#$`3`
#[1] 3 5

#$`4`
#[1] 1 2 5

#$`5`
#[1] 1 2 4

Or with tapply

tapply(as.logical(m), row(m), FUN = which)
#$`1`
#[1] 1 2 4 5

#$`2`
#[1] 1 2 3 4

#$`3`
#[1] 3 5

#$`4`
#[1] 1 2 5

#$`5`
#[1] 1 2 4

Or using split with row

split(m * col(m), row(m))

and to remove the 0's

lapply(split(m * col(m), row(m)), setdiff, 0)

NOTE: All the solutions work.

data

m <- structure(c(1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 
0, 0, 1, 1, 0, 1, 1, 0), .Dim = c(5L, 5L))

Upvotes: 0

markus
markus

Reputation: 26343

A second option using which and aggregate

out <- aggregate(col ~ row, which(m == 1, arr.ind = TRUE), c)
out
#  row        col
#1   1 1, 2, 4, 5
#2   2 1, 2, 3, 4
#3   3       3, 5
#4   4    1, 2, 5
#5   5    1, 2, 4

(not sure if this is your expected output though)

str(out)
#'data.frame':  5 obs. of  2 variables:
# $ row: int  1 2 3 4 5
# $ col:List of 5
#  ..$ 1: int  1 2 4 5
#  ..$ 2: int  1 2 3 4
#  ..$ 3: int  3 5
#  ..$ 4: int  1 2 5
#  ..$ 5: int  1 2 4

data

Kindly taken from @Telepresence

set.seed(42)
m = matrix(sample(0:1, 25, TRUE), 5, 5)
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    1    1    0    1    1
#[2,]    1    1    1    1    0
#[3,]    0    0    1    0    1
#[4,]    1    1    0    0    1
#[5,]    1    1    0    1    0

Upvotes: 1

Telepresence
Telepresence

Reputation: 629

set.seed(42)
m = matrix(sample(0:1, 25, TRUE), 5, 5)
apply(m, 1, function(x) which(x == 1))
#[[1]]
#[1] 1 2 4 5

#[[2]]
#[1] 1 2 3 4

#[[3]]
#[1] 3 5

#[[4]]
#[1] 1 2 5

#[[5]]
#[1] 1 2 4

Upvotes: 2

Related Questions