Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

access plyr id variables within functions

Tags:

r

plyr

I regulary have the problem that I need to access the actual id variable when using d*ply or l*ply. A simple (yet nonsense) example would be:

df1 <- data.frame( p = c("a", "a", "b", "b"), q = 1:4 )
df2 <- data.frame( m = c("a", "b" ), n = 1:2 )

d_ply( df1, "p", function(x){
 actualId <- unique( x$p )
 print( mean(x$q)^df2[ df2$m == actualId, "n" ] )
})

So in case of d*ply functions I can help myself with unique( x$p ). But when it comes to l*ply, I have no idea how to access the name of the according list element.

l_ply( list(a = 1, b = 2, c = 3), function(x){
  print( <missing code> )
})
# desired output
[1] "a"
[1] "b"
[1] "c"

Any suggestions? Anything I am ignoring?

like image 297
Beasterfield Avatar asked Jan 31 '13 13:01

Beasterfield


3 Answers

One way I've gotten around this is to loop over the index (names) and do the subsetting within the function.

l <- list(a = 1, b = 2, c = 3)
l_ply(names(l), function(x){
  print(x)
  myl <- l[[x]]
  print(myl)
})

myl will then be the same as

l_ply(l, function(myl) {
  print(myl)
})
like image 152
Brian Diggs Avatar answered Nov 15 '22 01:11

Brian Diggs


Here's one idea.

l_ply( list(a = 1, b = 2, c = 3), function(x){
     print(eval(substitute(names(.data)[i], parent.frame())))
})
# [1] "a"
# [1] "b"
# [1] "c"

(Have a look at the final code block of l_ply to see where I got the names .data and i.)

like image 2
Josh O'Brien Avatar answered Nov 14 '22 23:11

Josh O'Brien


I'm not sure there's a way to do that, because the only argument to your anonymous function is the list element value, without its name :

l_ply( list(a = 1, b = 2, c = 3), function(x){
  print(class(x))
})
[1] "numeric"
[1] "numeric"
[1] "numeric"

But if you get back the results of your command as a list or a data frame, the names are preserved for you to use later :

llply( list(a = 1, b = 2, c = 3), function(x){
  x
})
$a
[1] 1

$b
[1] 2

$c
[1] 3

Aside from Josh solution, you can also pass both names and values of your list elements to a function with mapply or m*ply :

d <- list(a = 1, b = 2, c = 3)
myfunc <- function(value, name) {
  print(as.character(name))
  print(value)
}
mapply(myfunc, d, names(d))
m_ply(data.frame(value=unlist(d), name=names(d)), myfunc)
like image 1
juba Avatar answered Nov 14 '22 23:11

juba