我正在使用一个特殊的利基函数,该函数要求将要分析的列的变量名写为对象名。我想在多个列上循环使用此函数,但是我不知道如何将列名解析为对象名才能使该函数正常工作。
这里是一个例子:
library(caper)
library(ape)
tree = rtree(100)
data = data.frame(taxa = tree$tip.label,
value1 = sample(c(0,1), 100, replace = TRUE),
value2 = sample(c(0,1), 100, replace = TRUE))
for(i in 2:3){
phylo.d(data = data, phy = tree,
names.col = taxa,
binvar = eval(substitute(colnames(data)[i]))
)
}
我遇到的问题是binvar参数。我目前在那里的代码无法正常工作,但这是我的最佳猜测。这应该返回错误:
Error in phylo.d(data = data, phy = tree, names.col = taxa, binvar = eval(substitute(colnames(data)[i]))) : 'eval(substitute(colnames(data)[i]))' is not a variable in data.
从names.col
上方的参数中可以看到函数如何期望输入列名(如对象名)。然后,该函数使用deparse(substitute(binvar))
从数据框中提取列。
有人可以提出解决方案吗? (除了重写功能)。
答案 0 :(得分:1)
我的方法是在传递给evaluate
之前为ENTIRE函数调用构建一个字符串。在这种情况下,循环的迭代将产生:
str="phylo.d(data=data,phy=tree,names.col=taxa,binvar=value1)"
str="phylo.d(data=data,phy=tree,names.col=taxa,binvar=value2)"
然后使用print(eval(str2expression(str)))
进行评估。我使用print是因为phylo.d
似乎会产生不可见的输出。
如果您想将调用的输出保存到phylo.d
,则在上面的字符串中建立一个赋值,并删除print
语句。
如果您对rlang
软件包和准引号感到满意,则可以构建更整洁的解决方案。
这是我的完整解决方案:
build.expr=function(i) {
paste("phylo.d(data=data,phy=tree,names.col=taxa,binvar=",
colnames(data) [i],")",sep='')
}
for (i in 2:3) {
print( eval(str2expression(build.expr(i))))
}
仅供参考:这是自您询问以来我的sessionInfo。
> sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 19.10
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.3.7.so
locale:
[1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8
[4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8
[7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C
[10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] compiler_3.6.1 tools_3.6.1
当我键入?str2expression时,它会显示一个以R为基数的软件包。