tags:

views:

57

answers:

3

Consider the following situation where I have a list of n matrices (this is just dummy data in the example below) in the object myList

mat <- matrix(1:12, ncol = 3)
myList <- list(mat1 = mat, mat2 = mat, mat3 = mat, mat4 = mat)

I want to select a specific column from each of the matrices and do something with it. This will get me the first column of each matrix and return it as a matrix (lapply() would give me a list either is fine).

sapply(myList, function(x) x[, 1])

What I can't seem able to do is use [ directly as a function in my sapply() or lapply() incantations. ?'[' tells me that I need to supply argument j as the column identifier. So what am I doing wrong that this does't work?

> lapply(myList, `[`, j = 1)
$mat1
[1] 1

$mat2
[1] 1

$mat3
[1] 1

$mat4
[1] 1

Where I would expect this:

$mat1
[1] 1 2 3 4

$mat2
[1] 1 2 3 4

$mat3
[1] 1 2 3 4

$mat4
[1] 1 2 3 4

I suspect I am getting the wrong [ method but I can't work out why? Thoughts?

+1  A: 

It's because [ is a .Primitive function. It has no j argument. And there is no [.matrix method.

> `[`
.Primitive("[")
> args(`[`)
NULL
> methods(`[`)
 [1] [.acf*            [.AsIs            [.bibentry*       [.data.frame     
 [5] [.Date            [.difftime        [.factor          [.formula*       
 [9] [.getAnywhere*    [.hexmode         [.listof          [.noquote        
[13] [.numeric_version [.octmode         [.person*         [.POSIXct        
[17] [.POSIXlt         [.raster*         [.roman*          [.SavedPlots*    
[21] [.simple.list     [.terms*          [.ts*             [.tskernel* 

Though this really just begs the question of how [ is being dispatched on matrix objects...

Joshua Ulrich
+5  A: 

I think you are getting the 1 argument form of [. If you do lapply(myList, `[`, i =, j = 1) it works.

frankc
+1 Bravo! Very nicely done.
Joshua Ulrich
+1 So this works: lapply(myList, `[`, i = , j = 1)
Shane
Took a while to figure out how to escape backticks inside inline code. Use <code>`foo`</code>. See http://meta.stackoverflow.com/questions/12694/escaping-backticks-fails
Richie Cotton
@user275455 - I thought I'd tried that version. Still doesn't answer the real underlying Q of why supplying only `j` doesn't work. But thanks for that.
Gavin Simpson
@Ritchie - thanks for that. Struggled and give up with it when composing my question, hence the `?'['` :-)
Gavin Simpson
@user275455 As I note in my own answer below, the argument names are ignored, and it is the positional matching that is important, and that is why your answer works. Thanks for the insight. Accepted.
Gavin Simpson
+2  A: 

After two pints of Britain's finest ale and a bit of cogitation, I realise that this version will work:

lapply(myList, `[`, , 1)

i.e. don't name anything and treat it like I had done mat[ ,1]. Still don't grep why naming j doesn't work...

...actually, having read ?'[' more closely, I notice the following section:

Argument matching:

     Note that these operations do not match their index arguments in
     the standard way: argument names are ignored and positional
     matching only is used.  So ‘m[j=2,i=1]’ is equivalent to ‘m[2,1]’
     and *not* to ‘m[1,2]’.

And that explains my quandary above. Yeah for actually reading the documentation.

Gavin Simpson
I'm pretty sure the reason is that `[` is a primitive method and so ignores argument names.
hadley