Erez Shomron
2024-Jul-05 11:35 UTC
[R] Bug? plot.formula does need support plot.first / plot.last param in plot.default
Is the following a bug in your opinion? I think so. This works as expected: ``` with(mtcars, plot(wt, mpg, plot.first = { plot.window(range(wt), range(mpg)) arrows(3, 15, 4, 30) })) ``` This does not. ``` plot(mpg ~ wt, data = mtcars, plot.first = { plot.window(range(wt), range(mpg)) arrows(3, 15, 4, 30) }) ``` With error: ``` Error in arrows(3, 15, 4, 30) : plot.new has not been called yet ``` The second example should work.>From the docs:?plot.formula " For the ?plot? method the formula can be of the form ?~ z + y + z?: the variables specified on the right-hand side are collected into a data frame, subsetted if specified, and displayed by ?plot.data.frame?. " ?plot.data.frame " ...: further arguments to ?stripchart?, ?plot.default? or ?pairs?. " And plot.default has both plot.first and plot.last It seems very arbitrary you can't use these parameters with the plot.formula method specifically.> sessionInfo()R version 4.4.1 (2024-06-14) Platform: x86_64-suse-linux-gnu Running under: openSUSE Tumbleweed [...]
Duncan Murdoch
2024-Jul-05 22:05 UTC
[R] Bug? plot.formula does need support plot.first / plot.last param in plot.default
That definitely looks like a bug, but not one that anyone will be eager to fix. It's very old code that tried to be clever, and that's the hardest kind of code to fix. Remember Kernighan's Law: "Everyone knows that debugging is twice as hard as writing a program in the first place. So if you?re as clever as you can be when you write it, how will you ever debug it?" Duncan Murdoch On 2024-07-05 7:35 a.m., Erez Shomron wrote:> Is the following a bug in your opinion? I think so. > > This works as expected: > > ``` > with(mtcars, plot(wt, mpg, plot.first = { > plot.window(range(wt), range(mpg)) > arrows(3, 15, 4, 30) > })) > ``` > > This does not. > > ``` > plot(mpg ~ wt, data = mtcars, plot.first = { > plot.window(range(wt), range(mpg)) > arrows(3, 15, 4, 30) > }) > ``` > > With error: > ``` > Error in arrows(3, 15, 4, 30) : plot.new has not been called yet > ``` > > The second example should work. > > From the docs: > > ?plot.formula > " For the ?plot? method the formula can be of the form ?~ z + y + > z?: the variables specified on the right-hand side are collected > into a data frame, subsetted if specified, and displayed by > ?plot.data.frame?. > " > > ?plot.data.frame > " ...: further arguments to ?stripchart?, ?plot.default? or ?pairs?. > " > > And plot.default has both plot.first and plot.last > > It seems very arbitrary you can't use these parameters with the plot.formula method specifically. > >> sessionInfo() > R version 4.4.1 (2024-06-14) > Platform: x86_64-suse-linux-gnu > Running under: openSUSE Tumbleweed > [...] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
Ivan Krylov
2024-Jul-06 14:24 UTC
[R] Bug? plot.formula does need support plot.first / plot.last param in plot.default
? Fri, 05 Jul 2024 14:35:40 +0300 "Erez Shomron" <r-mails at erezsh.org> ?????:> This works as expected:> with(mtcars, plot(wt, mpg, plot.first = { > plot.window(range(wt), range(mpg)) > arrows(3, 15, 4, 30) > }))I think you meant panel.first, not plot.first. At least I cannot find any mention of plot.first in the R source code. In this example, plot.first ends up being an argument of an internal call from plot.default() to plot.window(), which evaluates its ellipsis arguments. If your plot.first expression returned a non-NULL value, you would also have received a warning: plot.window(0:1, 0:1, plot.first = message('hello')) # hello plot.window(0:1, 0:1, plot.first = 123) # Warning message: # In plot.window(0:1, 0:1, plot.first = 123) : # "plot.first" is not a graphical parameter It is indeed documented that "passing [panel.first] from other ?plot? methods may well not work since it may be evaluated too early". The plot.formula method deliberately evaluates the arguments in the ellipsis, and the workaround suggested in https://bugs.r-project.org/show_bug.cgi?id=14591 doesn't help because the expression is then evaluated in an undesired environment (parent frame, not data). You are correct that plot.formula tries to evaluate all its remaining arguments in the context of the data passed to the method. In order for the lazy evaluation to work, plot.formula would have to (1) know and skip all such arguments by name on line 6, minding partial matching, (2) rewrite them into the form evalq(original_argument_expression, model_frame, parent_frame) so that they would be able to access both the data and the variables visible in the frame of the caller, and (3) give these expressions to do.call() in place of the original ones. (1) sounds especially brittle since plot.formula() may dispatch to other plot.* methods. Additionally, great care will need to be taken not to break existing code that calls plot.formula, even if it's already full of workarounds for plot.formula's behaviour. -- Best regards, Ivan
Reasonably Related Threads
- Bug? plot.formula does need support plot.first / plot.last param in plot.default
- Bug? plot.formula does need support plot.first / plot.last param in plot.default
- how to plot a graph with different pch
- suggestion: "." in [lsv]apply()
- C API - no NULL pointer guarantee?