Skip to content

Instantly share code, notes, and snippets.

@fditraglia
Created August 22, 2016 18:17
Show Gist options
  • Save fditraglia/5cf6e5029b2572cc4d858b15be37db38 to your computer and use it in GitHub Desktop.
Save fditraglia/5cf6e5029b2572cc4d858b15be37db38 to your computer and use it in GitHub Desktop.
A simple example of how to collapse a 3d array into a matrix in R
# ------------------------------------------------------------------------------
# Here's a simple but slightly confusing task in R: collapsing a 3d array into a
# matrix. Specifically, we want to convert a 3d array of this form:
# ------------------------------------------------------------------------------
# , , 1
#
# [,1] [,2] [,3]
# [1,] "1.1.1" "1.2.1" "1.3.1"
# [2,] "2.1.1" "2.2.1" "2.3.1"
#
# , , 2
#
# [,1] [,2] [,3]
# [1,] "1.1.2" "1.2.2" "1.3.2"
# [2,] "2.1.2" "2.2.2" "2.3.2"
#
# , , 3
#
# [,1] [,2] [,3]
# [1,] "1.1.3" "1.2.3" "1.3.3"
# [2,] "2.1.3" "2.2.3" "2.3.3"
#
# , , 4
#
# [,1] [,2] [,3]
# [1,] "1.1.4" "1.2.4" "1.3.4"
# [2,] "2.1.4" "2.2.4" "2.3.4"
# ------------------------------------------------------------------------------
# into a matrix of this form:
# ------------------------------------------------------------------------------
# [,1] [,2] [,3]
# [1,] "1.1.1" "1.2.1" "1.3.1"
# [2,] "2.1.1" "2.2.1" "2.3.1"
# [3,] "1.1.2" "1.2.2" "1.3.2"
# [5,] "2.1.2" "2.2.2" "2.3.2"
# [5,] "1.1.3" "1.2.3" "1.3.3"
# [6,] "2.1.3" "2.2.3" "2.3.3"
# [7,] "1.1.4" "1.2.4" "1.3.4"
# [8,] "2.1.4" "2.2.4" "2.3.4"
# ------------------------------------------------------------------------------
# We can do this efficiently using two base R functions: aperm and dim. If you
# aren't familiar with it, aperm is a generalization of the tranpose function t
# for matrices to arbitrary arrays.
# ------------------------------------------------------------------------------
collapse_3d_array <- function(myarray){
out <- aperm(myarray, c(1, 3, 2))
dim(out) <- c(dim(myarray)[1] * dim(myarray)[3], dim(myarray)[2])
return(out)
}
# ------------------------------------------------------------------------------
# Let's test it on the example from above:
# ------------------------------------------------------------------------------
test_array <- structure(c("1.1.1", "2.1.1", "1.2.1", "2.2.1", "1.3.1", "2.3.1",
"1.1.2", "2.1.2", "1.2.2", "2.2.2", "1.3.2", "2.3.2",
"1.1.3", "2.1.3", "1.2.3", "2.2.3", "1.3.3", "2.3.3",
"1.1.4", "2.1.4", "1.2.4", "2.2.4", "1.3.4", "2.3.4"),
.Dim = c(2L, 3L, 4L))
test_array
collapse_3d_array(test_array)
# ------------------------------------------------------------------------------
# It works! But how efficient is this for large-scale problems? Let's test it
# with a large array of normal random variates:
# ------------------------------------------------------------------------------
system.time(big_array <- array(rnorm(100 * 10 * 10000), c(100, 10, 10000)))
system.time(big_matrix <- collapse_3d_array(big_array))
# ------------------------------------------------------------------------------
# On my machine, the time required to create big_array is about 0.6 seconds
# compared to 0.06 to collapse it to big_array. Given that big_array is 76.3 Mb
# this is pretty fast!
# ------------------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment