How can I autostart a plot with a call to R who created it?

R-graphics are great for exploring data, as it often has very smart defaults. For example, when building with a formula, labels for the graph axes are inferred from the formula. In other words, the following two calls produce the same output:

plot(x~y) plot(x~y, xlab="x", ylab="y") 

Is there a way to get a similar “smart startup”?

For example, I would like to name

 plot(x~y, main=<something>) 

And create the same output as the call

 plot(x~y, main="plot(x~y)") 

If <something> inserts a call used by some introspection.

Is there a way to do this in R, either through some standard mechanism or an external package?

edit: One suggestion was to specify the formula as a string and provide it as an argument to call formula() , as well as main . This is useful, but it skips parameters that can affect the graph, for example, using subsets of data. To clarify, I would like

 x<-c(1,2,3) y<-c(1,2,3) z<-c(0,0,1) d<-data.frame(x,y,z) plot(x~y, subset(d, z==0), main=<something>) 

To have the same effect as

 plot(x~y, subset(d, z==0), main="plot(x~y, subset(d, z==0))") 
+7
source share
3 answers

I don't think this can be done without writing a thin wrapper around plot() . The reason is that R evaluates the “provided arguments” in the evaluation frame of the calling function, in which there is no way to access the current function call ( see here for details ).

In contrast, “default arguments” are evaluated in the function evaluation frame, from where introspection is possible. Here are a few possibilities (differing only in whether you want "myPlot" or "plot" to appear in the header:

 ## Function that reports actual call to itself (ie 'myPlot()') in plot title. myPlot <- function(x,...) { cl <- deparse(sys.call()) plot(x, main=cl, ...) } ## Function that 'lies' and says that plot() (rather than myPlot2()) called it. myPlot2 <- function(x,...) { cl <- sys.call() cl[[1]] <- as.symbol("plot") cl <- deparse(cl) plot(x, main=cl, ...) } ## Try them out x <- 1:10 y <- 1:10 par(mfcol=c(1,2)) myPlot(x,y) myPlot2(y~x) 

Here's a more general solution:

 plotCaller <- function(plotCall, ...) { main <- deparse(substitute(plotCall)) main <- paste(main, collapse="\n") eval(as.call(c(as.list(substitute(plotCall)), main=main, ...))) } ## Try _it_ out plotCaller(hist(rnorm(9999), breaks=100, col="red")) library(lattice) plotCaller(xyplot(rnorm(10)~1:10, pch=16)) ## plotCaller will also pass through additional arguments, so they take effect ## without being displayed plotCaller(xyplot(rnorm(10)~1:10), pch=16) 

deparse will try to break the dewaxed strings if they are too long (60 characters by default). When he does this, he returns a row vector. plot methods assume that "main" is one line, so the line main <- paste(main, collapse='\n') deals with this, concatenating all the strings returned by deparse, concatenating them using \n .

Here is an example of where it is needed:

 plotCaller(hist(rnorm(9999), breaks=100, col="red", xlab="a rather long label", ylab="yet another long label")) 
+7
source

Of course have! Here ya go:

 x = rnorm(100) y = sin(x) something = "y~x" plot(formula(something),main=something) 

enter image description here

+3
source

Perhaps you are thinking about match.call functionality. However, this really only works when called inside a function, and not as an argument. You can create your wrapper function that will call match.call , then pass everything else to plot or replace it to capture the call, and then change it with a call before evaluating:

 x <- runif(25) y <- rnorm(25, x, .1) myplot <- function(...) { tmp <- match.call() plot(..., main=deparse(tmp)) } myplot( y~x ) myplot( y~x, xlim=c(-.25,1.25) ) ## or myplot2 <- function(FUN) { tmp1 <- substitute(FUN) tmp2 <- deparse(tmp1) tmp3 <- as.list(tmp1) tmp4 <- as.call(c(tmp3, main=tmp2)) eval(tmp4) } myplot2( plot(y~x) ) myplot2( plot(y~x, xlim=c(-.25,1.25) ) ) 
+3
source

All Articles