You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在lapply与Map中保持函数调用属性的一致性?

问题:在lapply中保留函数调用属性里的原始对象名称

我想把函数调用作为attr属性附加到结果中。直接调用fn()时一切正常,但用lapply()运行时,d=参数对应的属性值显示为X[[i]],而不是实际传入的df1、df2等名称,我希望看到的是df1和df2而非X[[i]]。

> fn <- \(d, x=x, y=999, ...) {
+   cl <- match.call()
+   fa <- formals(fn)
+   fa[length(fa)] <- NULL
+   ma <- setdiff(names(fa), names(cl))
+   cl[ma] <- fa[ma]
+   cl[-c(1, 2)] <- lapply(cl[-c(1, 2)], eval, envir=parent.frame())
+   # cl$d <- quote(d)
+   res <- d[[1]]  ## so `res` depends on `d`
+   attr(res, 'call') <- cl
+   return(res)
+ }
> 
> z. <- 777
> df1 <- lst$df1
> df2 <- lst$df2
> fn(df1, x=666, z=z.)
[1] 1 2 3
attr(,"call")
fn(d = df1, x = 666, z = 777, y = 999)
> lapply(list(df1=df1, df2=df2), fn, x=666, z=z.)
$df1
[1] 1 2 3
attr(,"call")
FUN(d = X[[i]], x = 666, z = 777, y = 999)

$df2
[1] 1 2 3
attr(,"call")
FUN(d = X[[i]], x = 666, z = 777, y = 999)

这显然和之前的问题相关,我尝试了推荐的Map方法,但通用性不佳:

> Map(list(df1=df1, df2=df2), f=fn, x=666, z=z.)
$df1
[1] 1 2 3
attr(,"call")
(\(d, x=x, y=999, ...) {
  cl <- match.call()
  fa <- formals(fn)
  fa[length(fa)] <- NULL
  ma <- setdiff(names(fa), names(cl))
  cl[ma] <- fa[ma]
  cl[-c(1, 2)] <- lapply(cl[-c(1, 2)], eval, envir=parent.frame())
  # cl$d <- quote(d)
  res <- d[[1]]
  attr(res, 'call') <- cl
  return(res)
})(d = dots[[1L]][[2L]], x = 666, z = 777, y = 999)

$df2
[1] 1 2 3
attr(,"call")
(\(d, x=x, y=999, ...) {
  cl <- match.call()
  fa <- formals(fn)
  fa[length(fa)] <- NULL
  ma <- setdiff(names(fa), names(cl))
  cl[ma] <- fa[ma]
  cl[-c(1, 2)] <- lapply(cl[-c(1, 2)], eval, envir=parent.frame())
  # cl$d <- quote(d)
  res <- d[[1]]
  attr(res, 'call') <- cl
  return(res)
})(d = dots[[1L]][[2L]], x = 666, z = 777, y = 999)

之后我尝试了cl$d <- quote(d)、cl$d <- quote(substitute(d))、cl$d <- quote(eval(parse(text=d)))、cl$d <- quote(get(d))等方法(如代码中注释部分),但都无效。以下是cl$d <- quote(d)版本的结果:

> fn(df1, x=666, z=z.)
[1] 1 2 3
attr(,"call")
fn(d = d, x = 666, z = 777, y = 999)
> lapply(list(df1=df1, df2=df2), fn, x=666, z=z.)
$df1
[1] 1 2 3
attr(,"call")
FUN(d = d, x = 666, z = 777, y = 999)

$df2
[1] 1 2 3
attr(,"call")
FUN(d = d, x = 666, z = 777, y = 999)

期望输出

> lapply(list(df1=df1, df2=df2), fn, x=666, z=z.)
$df1
[1] TRUE
attr(,"call")
FUN(d = df1, x = 666, z = 777, y = 999)

$df2
[1] TRUE
attr(,"call")
FUN(d = df2, x = 666, z = 777, y = 999)

注意:寻求基于base R的解决方案。


补充说明

在@MrFlick的回答后,补充说明:实际我有一个大型列表lst,尝试以下代码时出现错误:

> lst <- list(df1=df1, df2=df2)
> lapply(lst, function(x) 
+   do.call("fn", list(as.name(x), x=666, z=z.))
+ )
Error in as.vector(x, mode = mode) : 
  'list' object cannot be coerced to type 'symbol'

内容的提问来源于stack exchange,提问作者jay.sf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 11:22:05