21

I would like use a function that uses the standard deparse(substitute(x)) trick within lapply. Unfortunately I just get the argument of the loop back. Here's my completely useless reproducible example:

# some test data
a <- 5
b <- 6 
li <- list(a1=a,b2=b)

# my test function
tf <- function(obj){
nm <- deparse(substitute(obj))
res <- list(myName=nm)
res
}

tf(a)
#returns
$myName
[1] "a"

which is fine. If I use lapply I either get [[1L]] or the x argument of an anonymous function.

lapply(li,function(x) tf(x))
# returns
$a1
$a1$myName
[1] "x"


$b2
$b2$myName
[1] "x"

Is there any way to obtain the following?

$a1
$a1$myName
[1] "a1"


$b2
$b2$myName
[1] "b1"

If there's anything more general on deparse(substitute(x)) and lapply I'd also eager to know.

EDIT: The problem as opposed to using an anonymous function that accepts multiple arguments and can thus use the name of the object and the object itself does not work because, the tf function will only accept one argument. So this does not work here...

Community
  • 1
  • 1
Matt Bannert
  • 27,631
  • 38
  • 141
  • 207
  • 2
    As with most of R, `lapply` passes the values to functions, not the variable references. – James Aug 29 '13 at 10:56
  • Thanks for the pointer James, I guess I was able to find something comparable here: http://stackoverflow.com/questions/9950144/access-lapply-index-names-inside-fun/9950734#9950734 . I will check it and either delete this questions as a duplicate or add an answer as soon as I am able to answer my own question. – Matt Bannert Aug 29 '13 at 11:01

1 Answers1

7

A possible solution :

lapply(li, function(x) {
  call1 <-  sys.call(1)
  call1[[1]] <- as.name("names")
  call1 <- call1[1:2]
  nm <- eval(call1)
  y <- deparse(substitute(x))
  y <- gsub("\\D", "", y)
  y <- as.numeric(y)
  list(myname=nm[y])
})
droopy
  • 2,788
  • 1
  • 14
  • 12
  • 3
    Very clever way to get the call. Your function can be simplified to this: `lapply(li, function(x)names(eval(sys.call(1)[[2]]))[substitute(x)[[3]]])`. Note that `sys.call(1)[[2]]` returns the symbol or expression used as the list argument to `lapply`, and `substitute(x)[[3]]` returns the current index in the loop. – Ferdinand.kraft Aug 29 '13 at 13:46
  • I really your way but at each iteration you will have to call the object (eval(sys.call(1))) instead of object's names. Could it be less powerful with large objects? – droopy Aug 29 '13 at 14:14
  • `eval(sys.call(1)[[2]])` will result in a symbol usually, `li` in this case, and probably does not cause duplication of the object it references, since this is passed to `names` which is a primitive function. As an alternative, you can save the names `nm <- names(li)` first and then use `lapply(li, function(x)nm[substitute(x)[[3]]])`. – Ferdinand.kraft Aug 29 '13 at 14:22