在lapply中使用deparse(substitute(x))?

21

我希望使用一个函数,在lapply中使用标准的deparse(substitute(x))技巧。不幸的是,我只能得到循环的参数。以下是我的完全无用的可重现示例:

# 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"

这很好。如果我使用lapply,我要么得到[[1L]],要么是匿名函数的x参数。

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


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

有没有办法获得以下内容?

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


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

如果关于deparse(substitute(x))lapply还有更常见的问题,我也很想知道。

编辑: 使用接受多个参数并因此可以使用对象名称和对象本身名称的匿名函数与使用不同之处在于,tf函数只接受一个参数。因此,这里无法正常工作...


2
与大多数R语言一样,lapply将值传递给函数,而不是变量引用。 - James
谢谢你的指引,James。我在这里找到了一个类似的东西:https://dev59.com/AWkw5IYBdhLWcg3wXZX8#9950734。我会检查它,并且要么删除这个问题作为重复,要么在我自己回答问题之前添加一个答案。 - Matt Bannert
1个回答

7
一个可能的解决方案:
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])
})

3
获取调用方式非常聪明。您的函数可以简化为:lapply(li, function(x)names(eval(sys.call(1)[[2]]))[substitute(x)[[3]]])。请注意,sys.call(1)[[2]]返回作为lapply列表参数使用的符号或表达式,而substitute(x)[[3]]返回循环中当前索引。 - Ferdinand.kraft
我真的很喜欢你的方式,但在每次迭代中,您将不得不调用对象(eval(sys.call(1)))而不是对象的名称。对于大型对象,它可能会变得不那么强大吗? - droopy
eval(sys.call(1)[[2]])通常会产生一个符号,例如在这种情况下是li,并且可能不会导致所引用的对象重复,因为它被传递给了原始函数names。作为替代方案,您可以先保存名称nm <- names(li),然后使用lapply(li, function(x)nm[substitute(x)[[3]]]) - Ferdinand.kraft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接