R的绘图非常适合数据探索,因为它通常具有非常智能的默认值。例如,在使用公式绘图时,绘图轴的标签从公式派生。换句话说,以下两个调用产生相同的输出:
plot(x~y)
plot(x~y, xlab="x", ylab="y")
有没有办法获得类似的“智能自动标题”?
例如,我想致电
plot(x~y, main=<something>)
并产生与调用
相同的输出plot(x~y, main="plot(x~y)")
<something>
使用某种内省插入使用的调用。
是否有通过某种标准机制或外部包在R中执行此操作的工具?
编辑:一个建议是将公式指定为字符串,并将其作为参数提供给formula()
调用以及main
。这很有用,但是它会错过参数而不会影响绘图,例如使用数据子集。详细说明,我想
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>)
与
具有相同的效果plot(x~y, subset(d, z==0), main="plot(x~y, subset(d, z==0))")
答案 0 :(得分:7)
如果不在plot()
周围写一个薄的包装,我认为不能做到这一点。原因是R在调用函数的求值框架中计算“提供的参数”,其中无法访问当前函数调用(see here for details)。
相比之下,“默认参数”在函数的评估框架中进行评估,从中可以进行内省 。这里有几种可能性(不同之处在于您是否希望“myPlot”或“plot”出现在标题中:
## Function that reports actual call to itself (i.e. '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)
这是一个更通用的解决方案:
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)
如果deparseed行太长(默认值为60个字符),它将尝试断开已解除的行。当它这样做时,它返回一个字符串向量。 plot方法假设'main'是一个单独的字符串,因此行main <- paste(main, collapse='\n')
通过连接deparse返回的所有字符串来处理这一点,并使用\n
连接它们。
以下是必要的示例:
plotCaller(hist(rnorm(9999), breaks=100, col="red", xlab="a rather long label",
ylab="yet another long label"))
答案 1 :(得分:3)
当然有!你走了:
x = rnorm(100)
y = sin(x)
something = "y~x"
plot(formula(something),main=something)
答案 2 :(得分:3)
您可能正在考虑match.call
的功能。但是,只有在函数内部调用时才能真正起作用,而不是作为参数传入。你可以创建你的包装函数,调用match.call
然后将所有其他内容传递给plot
或使用替换来捕获调用,然后在评估之前用调用修改它:
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) ) )