volatile
volatile

Reputation: 949

R strange apply returns

I use apply to a matrix in order to apply a function row by row. My syntax is as follows :

res = apply(X,1,MyFunc)

The above function MyFunc returns a list of two values. But the result of this apply application is a strange structure, where R seems to add some of its own (housekeeping?) data :

res = $`81`
$`81`$a
[1] 80.8078

$`81`$b
[1] 6247

Whereas the result I am waiting for is simply :

res = $a
[1] 80.8078

$b
[1] 6247

I do not know why this strange 81 is inserted by R and how can I get rid of it. Thanks for help

Upvotes: 0

Views: 1521

Answers (2)

Andrie
Andrie

Reputation: 179418

This is perfectly normal behaviour. You are applying a function over a matrix with named rows. Your function returns a list for each row, and each element in this new list of lists is named with the corresponding rowname.

Here is an example that reproduces what you describe:

x <- matrix(1:4, nrow=2)
rownames(x) <- 80:81

myFunc <- function(x)list(a=1, b=2)

xx <- apply(x, 1, myFunc)
xx

This returns:

$`80`
$`80`$a
[1] 1

$`80`$b
[1] 2


$`81`
$`81`$a
[1] 1

$`81`$b
[1] 2

Take a look at the structure of this list:

str(xx)
List of 2
 $ 80:List of 2
  ..$ a: num 1
  ..$ b: num 2
 $ 81:List of 2
  ..$ a: num 1
  ..$ b: num 2

To index the first element, simply use xx[[1]]:

xx[[1]]
$a
[1] 1

$b
[1] 2

Here is a guess as to what you may have intended... Rather than returning a list, if you return a vector, the result of the apply will be a matrix:

myFunc <- function(x)c(a=1, b=2)
apply(x, 1, myFunc)
  80 81
a  1  1
b  2  2

And to get a specific row, without names, do:

unname(xx[2, ])
[1] 2 2

Upvotes: 3

Blue Magister
Blue Magister

Reputation: 13363

It would help to know what your matrix (X) looks like. Let's try something like this:

mf <- function(x) list(a=sum(x),b=prod(x))
mat <- matrix(1:6,nrow=2)

Then:

> apply(mat,1,mf)
[[1]]
[[1]]$a
[1] 9

[[1]]$b
[1] 15


[[2]]
[[2]]$a
[1] 12

[[2]]$b
[1] 48

You need that first subscript to differentiate between the lists that each row will generate. I suspect that your rownames are numbered, which results in the $`81` that you are seeing.

Upvotes: 0

Related Questions