Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

extract a column from a matrix in a list in R

Tags:

r

I have a list of 100 elements. Each element is a list. And this list has two elements in them. One is just a key another is a matrix. This matrix has 5 columns in it. I am trying to extract one column from each of these matrices for all the elements. So basically I would have 100 matrices again as an element of the list. This is how the list looks like

a[[1]]
     [[1]]
          [1] "keyid"

      [[2]] 
              [,1]                [,2]          [,3]    [,4]    [,5]
          [1,] "1329397986.572332" "x" "y" "z" "a"
          [2,] "1329242747.368294" "x" "y" "z" "a"
          [3,] "1329194224.351232 "x" "y" "z" "a"

So what you can see here is a is a list and it has 100 elements. Each element is a list of 2 elements. I am currently interested only in the second element. The second element has a matrix. I would like to extract the first column of this matrix. Just to see if I can extract the column into a vector I can do

a[[1]][[2]][,1] 

and I get all the values as a vector, as follows.

a[[1]][[2]][,1]  
       [1] "1329397986.572332" "1329242747.368294" "1329194224.351232" 

But when I do

 x <- lapply(a,function(r){r[[2]][,1]})

the following is the error I get.

> x <- lapply(a, function(r){r[[2]][,1]})
Error in r[[2]][, 1] : incorrect number of dimensions

I am not sure why I am getting that. I checked the dimensions of the matrix element.

> dim(a[[1]][[2]])
  [1] 52  5

and it looks correct. So I am not sure where the error is.

dput(a) gives

dput(a)
[[1]]
[[1]][[1]]
[1] "keyid"

[[1]][[2]]
  [,1]                [,2]          [,3]    [,4]    [,5]
[1,] "1329397986.572332" "x"   "y"     "z"     "a"
[2,] "1329242747.368294" "x"   "y"     "z"     "a"
[3,] "1329194224.351232" "x"   "y"     "z"     "a"

[[2]]
[[2]][[1]]
[1] "keyid"

[[2]][[2]]
  [,1]                [,2]          [,3]    [,4]    [,5]
[1,] "1329397986.572332" "x"   "y"     "z"     "a"
[2,] "1329242747.368294" "x"   "y"     "z"     "a"
[3,] "1329194224.351232" "x"   "y"     "z"     "a"

...

[[100]]
[[100]][[1]]
[1] "keyid"

[[100]][[2]]
  [,1]                [,2]          [,3]    [,4]    [,5]
[1,] "1329397986.572332" "x"   "y"     "z"     "a"
[2,] "1329242747.368294" "x"   "y"     "z"     "a"
[3,] "1329194224.351232" "x"   "y"     "z"     "a"
like image 356
Bartha Avatar asked Apr 24 '13 02:04

Bartha


2 Answers

This seems a perfect case for the little-used function rapply.

Until a reproducible example is posted, I will post this as a possible solution

set.seed(1)
# a possible reproducible example
a <- replicate(5, list('a', matrix(runif(10), ncol=5)), simplify = FALSE)

# the first column
a1 <- rapply(a, classes = 'matrix', how = 'list', f = function(x) x[, 1, drop = FALSE]) 
# a second `lapply` is required to drop `NULL` entries

a1Only <- lapply(a1, Filter, f = Negate(is.null))
like image 137
mnel Avatar answered Oct 11 '22 04:10

mnel


Try this:

a <- list(list("keyid", structure(c("1329397986.572332", "1329242747.368294", 
"1329194224.351232", "x", "x", "x", "y", "y", "y", "z", "z", 
"z", "a", "a", "a"), .Dim = c(3L, 5L))), list("keyid", structure(c("1329397986.572332", 
"1329242747.368294", "1329194224.351232", "x", "x", "x", "y", 
"y", "y", "z", "z", "z", "a", "a", "a"), .Dim = c(3L, 5L))))

sapply( lapply(a, "[[" , 2) , "[", TRUE, 1)
     [,1]                [,2]               
[1,] "1329397986.572332" "1329397986.572332"
[2,] "1329242747.368294" "1329242747.368294"
[3,] "1329194224.351232" "1329194224.351232"

Explanation: the inner lapply pulls out the second element in each sublist, passing it on to the outer sapply. The (outer) sapply uses [ to pull out the first column from each of the objects passed to it. Since [ is a primitive function, .i.e. one that uses positional arguments only, you do need to use a placeholder which is the purpose for supplying the "TRUE" argument. It's purpose is to "push" the "1" over into second argument position and thereby make it a column-selector rather than a row-selector.

like image 5
IRTFM Avatar answered Oct 11 '22 06:10

IRTFM