16
votes

For a matrix (as.matrix), how can I generate a table where rows are equal to rows of the matrix?

>table(matrix)

and

>hist(matrix)

show the cumulative sum for each unique data value in the matrix, but I would like a table where rows are the same value as each matrix row, and table columns are the sum occurrence of each unique data value in the matrix.

Example matrix:

   1  2  3  4 
a  5  5  4  6    
b  5  5  5  5     
c  8  7  6  6   
d  2  6  6  6     
e  7  7  5  4      

Desired output table:

   2  4  5  6  7  8
a  0  1  2  1  0  0
b  0  0  4  0  0  0
c  0  0  0  2  1  1
d  1  0  0  3  0  0
e  0  1  1  0  2  0
4
There are two much more efficient and elegant than mine. You might want to consider removing the checkmark from my answer and placing it instead on one of the others (for example @GregoryDemin 's)Ricardo Saporta

4 Answers

10
votes

One alternative is to convert your matrix to a long data.frame (using stack), at which point you can easily use table:

Here's your data:

mymat <- structure(c(5L, 5L, 8L, 2L, 7L, 5L, 5L, 7L, 6L, 7L, 4L, 5L, 6L, 
            6L, 5L, 6L, 5L, 6L, 6L, 4L), .Dim = c(5L, 4L), .Dimnames = list(
              c("a", "b", "c", "d", "e"), c("1", "2", "3", "4")))

This is what it looks like as a long data.frame:

head(stack(data.frame(t(mymat))))
#   values ind
# 1      5   a
# 2      5   a
# 3      4   a
# 4      6   a
# 5      5   b
# 6      5   b

Here's how we can use that to create the table you want:

with(stack(data.frame(t(mymat))), table(ind, values))
#    values
# ind 2 4 5 6 7 8
#   a 0 1 2 1 0 0
#   b 0 0 4 0 0 0
#   c 0 0 0 2 1 1
#   d 1 0 0 3 0 0
#   e 0 1 1 0 2 0
7
votes
## source data
x=as.matrix(read.table(text="
   1  2  3  4 
a  5  5  4  6    
b  5  5  5  5     
c  8  7  6  6   
d  2  6  6  6     
e  7  7  5  4
"))

# result

table(rep(rownames(x),ncol(x)),c(x))

#   2 4 5 6 7 8
# a 0 1 2 1 0 0
# b 0 0 4 0 0 0
# c 0 0 0 2 1 1
# d 1 0 0 3 0 0
# e 0 1 1 0 2 0
4
votes

I used apply too:

t(apply(mat, 1, function(x) table(factor(x, levels = unique(sort(c(mat)))))))

R > mat  = matrix(sample(1:8, 20, replace = T), 5, 4)
R > mat
     [,1] [,2] [,3] [,4]
[1,]    5    6    1    4
[2,]    4    3    4    8
[3,]    4    8    4    3
[4,]    3    3    5    1
[5,]    1    1    3    1
R > t(apply(mat, 1, function(x) table(factor(x, levels = unique(sort(c(mat)))))))
     1 3 4 5 6 8
[1,] 1 0 1 1 1 0
[2,] 0 1 2 0 0 1
[3,] 0 1 2 0 0 1
[4,] 1 2 0 1 0 0
[5,] 3 1 0 0 0 0
2
votes

you can use apply over the rows, and then use mapply with an ifelse statement to get back your matrix.

Assuming X is your matrix:

# this will get you the values, just not in a nice matrix
tables.list <- apply(X, 1, table)

# unique values
vals <- sort(unique(c(X)))

# this will get you the matrix
results <- t(mapply(function(v, t)
   ifelse(v %in% names(t), t[as.character(v)], 0), list(vals), tables.list ))

# give it names
dimnames(results) <- list(rownames(X), vals)

results

#   2 4 5 6 7 8
# a 0 1 2 1 0 0
# b 0 0 4 0 0 0
# c 0 0 0 2 1 1
# d 1 0 0 3 0 0
# e 0 1 1 0 2 0