Hoping there's a simple answer here but I can't find it anywhere.
I have a numeric matrix with labelled rows and columns:
1 2 3 4
a 6 7 8 9
b 8 7 5 7
c 8 5 4 1
d 1 6 3 2
I would like a data.table (or a data.frame I can then convert) of the form:
col row value
1 a 6
1 b 8
1 c 8
1 d 1
2 a 7
2 b 7
2 c 5
2 d 6
...
Any tips appreciated.
Use melt
from reshape2:
library(reshape2)
#Fake data
x <- matrix(1:12, ncol = 3)
colnames(x) <- letters[1:3]
rownames(x) <- 1:4
x.m <- melt(x)
x.m
Var1 Var2 value
1 1 a 1
2 2 a 2
3 3 a 3
4 4 a 4
...
The as.table
and as.data.frame
functions together will do this:
> m <- matrix( sample(1:12), nrow=4 )
> dimnames(m) <- list( One=letters[1:4], Two=LETTERS[1:3] )
> as.data.frame( as.table(m) )
One Two Freq
1 a A 7
2 b A 2
3 c A 1
4 d A 5
5 a B 9
6 b B 6
7 c B 8
8 d B 10
9 a C 11
10 b C 12
11 c C 3
12 d C 4
Assuming 'm' is your matrix...
data.frame(col = rep(colnames(m), each = nrow(m)),
row = rep(rownames(m), ncol(m)),
value = as.vector(m))
This executes extremely fast on a large matrix and also shows you a bit about how a matrix is made, how to access things in it, and how to construct your own vectors.
You can use the function data.table()
with the parameter keep.rownames
to convert the matrix to the data.table class:
# Example data
x
a b c
1 1 5 9
2 2 6 10
3 3 7 11
4 4 8 12
# Conversion
data.table(x, keep.rownames = TRUE) # inserts rownames into column "rn"
rn a b c
1: 1 1 5 9
2: 2 2 6 10
3: 3 3 7 11
4: 4 4 8 12