R中如何向量化'deparse(substitute(d))'?传入c(dnorm,dcauchy)为何报错?
解答你的R函数问题:向量化处理与报错原因分析
咱们先解决你提到的报错问题,再聊向量化处理的方案,这样逻辑更顺~
问题2:为什么bb(d = c(dnorm, dcauchy))会报“object not found”?
你写的bb函数里,当传入的参数不是字符型时,会用deparse(substitute(d))把传入的表达式转成字符串。这里的关键是:substitute(d)会捕获你传入的整个调用表达式。
当你调用bb(d = c(dnorm, dcauchy))时,substitute(d)拿到的是c(dnorm, dcauchy)这个完整的调用,deparse()把它转成了字符串"c(dnorm, dcauchy)"。接下来循环里的get(d[i])就会尝试找一个叫c(dnorm, dcauchy)的对象——但这个对象根本不存在,R自然就报错了。
而你说的几个能正常运行的情况,原因很清晰:
bb(d = dnorm):substitute(d)拿到的是dnorm,转成字符串后get("dnorm")能正确获取正态密度函数;bb(d = c("dnorm", "dcauchy")):传入的是字符向量,函数直接用每个字符串去get对应的函数,完全没问题;- 至于你提到的
bb(d = c(dnorm))能正常执行,这大概率是个小疏漏——正常情况下get("c(dnorm)")会找不到对象,可能你实际测试的是c("dnorm")?😉
问题1:如何向量化处理deparse(substitute(d))?
要处理c(dnorm, dcauchy)这种函数向量的传入,我们不能再把整个c(...)表达式转成字符串,而是要拆解它,提取每个函数的名字,或者更直接地——直接处理函数对象本身,跳过转字符串再get的步骤。
方案1:拆解c(...)调用表达式(不依赖额外包)
修改函数逻辑,判断传入的是否是c()调用,然后提取里面的每个函数名:
bb <- function(d){ # 处理c(函数1, 函数2)这种调用 d_call <- substitute(d) if(is.call(d_call) && as.character(d_call)[1] == "c"){ d <- sapply(as.list(d_call)[-1], deparse) } else if(!is.character(d)){ # 单个函数的情况 d <- deparse(d_call) } h <- numeric(length(d)) for(i in seq_along(d)){ h[i] <- get(d[i])(1) } h }
现在调用bb(d = c(dnorm, dcauchy))就能正常返回两个函数在1处的取值了。
方案2:直接处理函数对象(更推荐)
其实我们完全可以跳过deparse和get的步骤,直接对传入的函数对象操作,这样逻辑更直观,也不容易出错:
bb <- function(d){ if(is.function(d)){ # 单个函数的情况 h <- d(1) } else if(is.list(d) && all(sapply(d, is.function))){ # 函数列表/向量的情况 h <- sapply(d, function(func) func(1)) } else if(is.character(d)){ # 字符向量的情况 h <- sapply(d, function(nm) get(nm)(1)) } else { # 处理符号引用(比如直接传函数名的情况) d_name <- deparse(substitute(d)) h <- get(d_name)(1) } h }
这个版本的函数兼容所有你提到的调用方式:
bb(d = dnorm)→ 返回dnorm(1)的结果bb(d = c(dnorm, dcauchy))→ 返回两个函数在1处的取值向量bb(d = c("dnorm", "dcauchy"))→ 同样返回正确结果
内容的提问来源于stack exchange,提问作者rnorouzian
相关产品推荐
相关产品推荐

