Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3339400
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T00:29:16+00:00 2026-05-18T00:29:16+00:00

I want to write a function that calls both plot() and legend() and it

  • 0

I want to write a function that calls both plot() and legend() and it would be ideal if the user could specify a number of additional arguments that are then passed through to either plot() or legend(). I know I can achieve this for one of the two functions using ...:

foo.plot <- function(x,y,...) {
    plot(x,y,...)
    legend("bottomleft", "bar", pch=1)
}

foo.plot(1,1, xaxt = "n")

This passes xaxt = "n" to plot. But is there a way for example to pass e.g. title = "legend" to the legend() call without prespecifying the arguments in the function header?


Update from the accepted answer: I thought that VitoshKa’s way was the most elegant to accomplish what I wanted. However, there were some minor issues that I had to get around with until it worked as I wanted.

At first, I checked which of the parameters I want to pass to legend and which to plot. First step to this end was to see which arguments of legend are unique to legend and not part of plot and/or par:

legend.args <- names(formals(legend))
plot.args <- c(names(formals(plot.default)), names(par()))
dput(legend.args[!(legend.args %in% plot.args)])

I use dput() here, because the line plot.args <- c(names(formals(plot.default)), names(par())) always calls a new empty plot which I did not want. So, I used the output of dput in the following function.

Next, I had to deal with the overlapping arguments (get them via dput(largs.all[(largs.all %in% pargs.all)])). For some this was trivial (e.g., x, y) others get passed to both functions (e.g., pch). But, in my real application I even use other strategies (e.g., different variable names for adj, but not implemented in this example).

Finally, the do.call function had to be changed in two ways. First, the what part (i.e., called functions) needs to be a character (i.e., 'plot' instead of plot). And the argument list must be constructed slightly different.

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))

In this example, pch is passed to both plot and legend, title is only passed to legend, and ylim only to plot.


Update 2 based on a comment by Gavin Simpson (see also the comments at Vitoshka’s answer):
(i) That’s correct.
(ii) It can always be a character. But if you have a variable with the same name as the function, then you need to quote the function name in 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) You can use c(x = 1, y = 1, list()) and it works fine. However, what I really did (not in the example I gave but in my real function) is the following: c(x = 1, y = 1, xlim = c(0, 2), list(bla='foo'))
Please compare this with: c(list(x = 1, y = 1, xlim = c(0, 2)), list(bla='foo'))
In the first case, the list contains two elements xlim, xlim1 and xlim2 (each a scalar), in the latter case the list has only xlim (which is vector of length 2, which is what I wanted).

So, you are right in all your points for my example. But, for my real function (with a lot more variables), I encountered these problems and wanted to document them here. Sorry for being imprecise.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T00:29:17+00:00Added an answer on May 18, 2026 at 12:29 am

    An automatic way:

    foo.plot <- function(x,y,...) {
        lnames <- names(formals(legend))
        pnames <- c(names(formals(plot.default)), names(par()))
        dots <- list(...)
        do.call('plot', c(list(x = x, y = x), dots[names(dots) %in% pnames]))
        do.call('legend', c("bottomleft", "bar", pch = 1, dots[names(dots) %in% lnames]))
    }
    

    pch must be filtered from the lnames to avoid duplication in the legend call in case the user supplies ‘pch’, but you got the idea.
    Edited Jan 2012 by Carl W: “do.call” only works with the functions in quotes, as in the updates by Henrik. I edited it here to avoid future confusion.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I want to write a function that identifies all the links on a particular
I want to write a function that takes a list of numbers and returns
i want to write a function that prints multi-dimensional objects which are text (or
I want to write 'twice' function that takes a function and an argument and
I want to write a function that read line by line from a socket
I have problem with fancybox. I want to write a function that will run
I want to write a cmp -like function that compares two version numbers and
You want to write unittest -cases for a function like that: def test_me(a): for
I want to write a function which would return me a Vector of the
I am trying to write a javascript function that calls an Dictionary value and

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.