Sakura
Sakura

Reputation: 729

Convert a matrix to columns

Assuming I have a matrix looks like below, the values up or down the diagonal are the same. In other words, [,1] x [2,] and [,2] x [1,] both are 2 in the matrix.

> m = cbind(c(1,2,3),c(2,4,5),c(3,5,6))
> m
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    2    4    5
[3,]    3    5    6

Then I have real name for 1, 2, and 3 as well.

>Real_name
A B C   # A represents 1, B represents 2, and C represents 3.

If I would like to convert the matrix to 3 columns containing corresponding real name for each pair, and the pair must be unique, A x B is the same as B x A, so we keep A x B only. How can I achieve it using R?

A A 1
A B 2 
A C 3 
B B 4 
B C 5
C C 6

Upvotes: 2

Views: 170

Answers (3)

akuiper
akuiper

Reputation: 214957

colnames(m) <- c("A", "B", "C")
rownames(m) <- c("A", "B", "C")

m[lower.tri(m)] = NA                   # replace lower triangular elements with NA
data.table::melt(m, na.rm = TRUE)        # melt and remove NA

#  Var1 Var2 value
#1    A    A     1
#4    A    B     2
#5    B    B     4
#7    A    C     3
#8    B    C     5
#9    C    C     6

Or you can do it in a single line: melt(replace(m, lower.tri(m), NA), na.rm = TRUE)

Upvotes: 3

Sandipan Dey
Sandipan Dey

Reputation: 23101

This will also work:

g <- expand.grid(1:ncol(m), 1:ncol(m))
g <- g[g[,2]>=g[,1],] 
cbind.data.frame(sapply(g, function(x) Real_name[x]), Val=m[as.matrix(g)])

  Var1 Var2 Val
1    A    A   1
2    A    B   2
3    B    B   4
4    A    C   3
5    B    C   5
6    C    C   6

Upvotes: 0

Zheyuan Li
Zheyuan Li

Reputation: 73295

The following is straightforward:

m <- cbind(c(1,2,3), c(2,4,5), c(3,5,6))
## read `?lower.tri` and try `v <- lower.tri(m, diag = TRUE)` to see what `v` is
## read `?which` and try `which(v, arr.ind = TRUE)` to see what it gives
ij <- which(lower.tri(m, diag = TRUE), arr.ind = TRUE)

Real_name <- LETTERS[1:3]
data.frame(row = Real_name[ij[, 1]], col = Real_name[ij[, 2]], val = c(m[ij]))

#  row col val
#1   A   A   1
#2   B   A   2
#3   C   A   3
#4   B   B   4
#5   C   B   5
#6   C   C   6

Upvotes: 3

Related Questions