Skip to content

Instantly share code, notes, and snippets.

@nilforooshan
Last active September 26, 2024 23:39
Show Gist options
  • Select an option

  • Save nilforooshan/3bb98f4a81bcd27a8bdd046cfc0e7d95 to your computer and use it in GitHub Desktop.

Select an option

Save nilforooshan/3bb98f4a81bcd27a8bdd046cfc0e7d95 to your computer and use it in GitHub Desktop.
R: Convert an upper.tri or a lower.tri data.frame to a full matrix

Convert an upper.tri or a lower.tri data.frame to a full matrix

The function:

tri.2full = function(df) # df is a data.frame with 3 columns
{
   dimmat = (sqrt(1+8*nrow(mydf))-1)/2 # Assuming 0 rows are not skipped.
   mat = matrix(, nrow=dimmat, ncol=dimmat)
   mat[upper.tri(mat, diag=TRUE)] = df[,3]
   mat[lower.tri(mat)] = t(mat)[lower.tri(mat)]
   return(mat)
}

Sample lower.tri data

(mydf = data.frame(x=c(1,1,2,1,2,3,1,2,3,4,1,2,3,4,5),
                   y=c(1,2,2,3,3,3,4,4,4,4,5,5,5,5,5),
                   z=11:25))

Input:

   x y  z
 1 1 1 11
 2 2 1 12
 3 2 2 13
 4 3 1 14
 5 3 2 15
 6 3 3 16
 7 4 1 17
 8 4 2 18
 9 4 3 19
10 4 4 20
11 5 1 21
12 5 2 22
13 5 3 23
14 5 4 24
15 5 5 25

Run the function on the data.

tri.2full(mydf)

Output:

     [,1] [,2] [,3] [,4] [,5]
[1,]   11   12   14   17   21
[2,]   12   13   15   18   22
[3,]   14   15   16   19   23
[4,]   17   18   19   20   24
[5,]   21   22   23   24   25

It also works for an upper.tri data.frame like this:

mydf = data.frame(x=c(1,1,2,1,2,3,1,2,3,4,1,2,3,4,5),
                  y=c(1,2,2,3,3,3,4,4,4,4,5,5,5,5,5),
                  z=11:25)

Things would get difficult if 0 elements are not printed in the file. In that case, you should know the dimension of the matrix that you are going to create.

tri.2full = function(df, dimmat) # df is a data.frame with 3 columns & dimmat is the matrix dimension
{
   df[,1] = as.integer(factor(df[,1]))
   df[,2] = as.integer(factor(df[,2]))
   mat = matrix(0, nrow=dimmat, ncol=dimmat)
   for(i in 1:dimmat)
   {
      print(i)
      tmp = df[df[,1]==i, 2:3]
      mat[i, tmp[,1]] = mat[tmp[,1], i] = tmp[,2]
   }
   return(mat)
}

tri.2full(mydf, 5)

Output:

     [,1] [,2] [,3] [,4] [,5]
[1,]   11   12   14   17   21
[2,]   12   13   15   18   22
[3,]   14   15   16   19   23
[4,]   17   18   19   20   24
[5,]   21   22   23   24   25

You may need to re-order the matrix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment