Есть ли способ использовать два оператора «…» в функции в R?

Я хочу написать функцию, которая вызывает как plot () , так и legend () , и было бы идеально, если бы пользователь мог указать ряд дополнительных аргументов, которые затем передаются через plot () или 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 () без предварительного указания аргументов в заголовке функции?


Обновление из принятого ответа : Я думал, что способ ВитошКа был самым элегантным для достижения того, что я хотел. Тем не мение, были некоторые незначительные проблемы, которые мне пришлось решить, пока все не заработало так, как я хотел.

Сначала я проверил, какие из параметров я хочу передать в легенду , а какие - в график . Первым шагом в этом направлении было выяснить, какие аргументы легенды являются уникальными для легенды и не являются частью сюжета и / или номинала:

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% в% pargs.all)]) ). Для некоторых это было тривиально (например, x , y ) остальные передаются обеим функциям (например, pch ). Но в моем реальном приложении я даже использую другие стратегии (например, другие имена переменных для adj , но не реализованные в этом примере).

Наконец, функция do.call пришлось изменить двумя способами. Во-первых, какая часть (т. Е. Вызываемые функции) должна быть символом (т. Е. '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 , так и в легенду , title ] передается только в легенду , а илим только в график . (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 '))
In в первом случае список содержит два элемента xlim , xlim1 и xlim2 (каждый скаляр), во втором случае список содержит только xlim (вектор длины 2, как я и хотел).

Итак, вы правы по всем пунктам моего примера. Но что касается моей реальной функции (с гораздо большим количеством переменных), я столкнулся с этими проблемами и хотел их здесь описать. Извините за неточность.

37
задан Henrik 11 November 2010 в 16:57
поделиться