我想编写一个同时调用plot()and的函数,legend()如果用户可以指定许多附加参数,然后将这些参数传递给plot()or 或,那将是理想的legend()。我知道我可以使用以下两个功能之一来实现这一点...:
foo.plot <- function(x,y,...) {
plot(x,y,...)
legend("bottomleft", "bar", pch=1)
}
foo.plot(1,1, xaxt = "n")
这传递xaxt = "n"给情节。但是有没有一种方法可以在不预先指定函数头中的参数的情况下传递title = "legend"给调用?legend()
接受答案的更新:我认为 VitoshKa 的方式是完成我想要的最优雅的方式。但是,我必须解决一些小问题,直到它按我的意愿工作。
起初,我检查了我要传递哪些参数legend以及要传递哪些参数plot。为此的第一步是查看哪些参数legend是唯一的,legend而不是情节和/或标准的一部分:
legend.args <- names(formals(legend))
plot.args <- c(names(formals(plot.default)), names(par()))
dput(legend.args[!(legend.args %in% plot.args)])
我dput()在这里使用,因为这条线plot.args <- c(names(formals(plot.default)), names(par()))总是调用一个我不想要的新空图。所以,我dput在下面的函数中使用了输出。
接下来,我必须处理重叠的参数(通过 获取它们dput(largs.all[(largs.all %in% pargs.all)]))。对于一些人来说这是微不足道的(例如,,x),y其他人则被传递给两个函数(例如,pch)。但是,在我的实际应用程序中,我什至使用了其他策略(例如,不同的变量名称用于adj,但未在此示例中实现)。
最后,do.call必须以两种方式更改该功能。首先,what 部分(即,称为函数)需要是一个字符(即,'plot'而不是plot)。并且参数列表的构造必须略有不同。
foo.plot <- function(x,y,...) {
leg.args.unique <- c("legend", "fill", "border", "angle", "density", "box.lwd", "box.lty", "box.col", "pt.bg", "pt.cex", "pt.lwd", "xjust", "yjust", "x.intersp", "y.intersp", "text.width", "text.col", "merge", "trace", "plot", "ncol", "horiz", "title", "inset", "title.col", "title.adj")
leg.args.all <- c(leg.args.unique, "col", "lty", "lwd", "pch", "bty", "bg", "cex", "adj", "xpd")
dots <- list(...)
do.call('plot', c(list(x = x, y = x), dots[!(names(dots) %in% leg.args.unique)]))
do.call('legend', c(list("bottomleft", "bar"), dots[names(dots) %in% leg.args.all]))
}
foo.plot(1,1,pch = 4, title = "legendary", ylim = c(0, 5))
在此示例中,pch传递给两者plot和legend,title仅传递给legend,并且ylim仅传递给plot。
根据 Gavin Simpson 的评论更新 2(另请参阅 Vitoshka 的回答中的评论):(
i)这是正确的。
(ii) 它总是可以是一个字符。但是如果你有一个与函数同名的变量,那么你需要在中引用函数名do.call:
min.plot <- function(x,y,plot=TRUE) if(plot == TRUE) do.call(plot, list(x = x, y = y))
min.plot(1,1)
Error in do.call(plot, list(x = x, y = y)) :
'what' must be a character string or a function
(iii)您可以使用c(x = 1, y = 1, list())并且效果很好。但是,我真正所做的(不是在我给出的示例中,而是在我的实际函数中)如下:c(x = 1, y = 1, xlim = c(0, 2), list(bla='foo'))
请将其与以下情况进行比较:c(list(x = 1, y = 1, xlim = c(0, 2)), list(bla='foo'))
在第一种情况下,列表包含两个元素和xlim(每个都是标量),在后一种情况下该列表只有(这是长度为 2 的向量,这是我想要的)。xlim1xlim2xlim
所以,对于我的例子,你的所有观点都是正确的。但是,对于我的实际功能(有更多变量),我遇到了这些问题,并想在这里记录它们。抱歉不准确。