Search code examples
rperformancercpp

Fastest way to transpose a list in R / Rcpp


I have a list:

ls <- list(c("a", "b", "c"), c("1", "2", "3"), c("foo", "bar", "baz"))
ls

#> [[1]]
#> [1] "a" "b" "c"

#> [[2]]
#> [1] "1" "2" "3"

#> [[3]]
#> [1] "foo" "bar" "baz"

which I wish to "transpose" to give:

resulting_ls

#> [[1]]
#> [1] "a"   "1"   "foo"

#> [[2]]
#> [1] "b"   "2"   "bar"

#> [[3]]
#> [1] "c"   "3"   "baz"

I can achieve this with:

mat <- matrix(unlist(ls), ncol = 3, byrow = TRUE)
resulting_ls <- lapply(1:ncol(mat), function(i) mat[, i])

But with my real data it's very slow...(and I need to do this for many lists each of which are much larger than example above)

My question:

What is the fastest way to do this for a large list length(ls) and/or length(ls[[i]])?

  1. in R (if this is not the case already)
  2. with Rcpp

Solution

  • In the data.table package, there's a transpose() function which does exactly this. It is implemented in C for speed.

    require(data.table) # v1.9.6+
    transpose(ls)
    # [[1]]
    # [1] "a"   "1"   "foo"
    
    # [[2]]
    # [1] "b"   "2"   "bar"
    
    # [[3]]
    # [1] "c"   "3"   "baz"
    

    It also fills automatically with NA in case the list elements are not of equal lengths, and also coerces automatically to the highest SEXPTYPE. You can provide a different value to the fill argument if necessary. Check ?transpose.