• R语言已解决
  • 【已解决】plot 函数的 xlab 和 ylab 的参数设置是否不一样

Cloud2016 可以看 plot.formula 方法的源代码:

> graphics:::plot.formula
function (formula, data = parent.frame(), ..., subset, ylab = varnames[response], 
  ask = dev.interactive()) 
{
  ...

我没有细看,但 ylab 这个参数确实是作了特殊处理,应该是在某个地方被执行了 eval() 导致 y[i] 被打回原形。

    yihui dapengde plot.formula 方法里确实对 ylab 的处理不一样,源代码不少,看起来有点晕,大家平时看源代码有什么辅助没有?

      Cloud2016 只看明白了一点:确实是对 ylab 经过了特殊处理。xlab 和 ylab 确实待遇不一样。其他的我就看不懂了。

      PS. ggplot 对方法 1 是支持的。

      gg <- ggplot(anscombe) + geom_point(aes(x1, y1))
      
      gg + 
        xlab(substitute(x[i], list(i = 1))) + 
        ylab(substitute(y[i], list(i = 1)))
      
      gg + 
        xlab(as.expression(substitute(x[i], list(i = 1)))) +
        ylab(as.expression(substitute(y[i], list(i = 1))))

        我之前没好好注意这个问题,就是 plot 是一个泛型函数,对于不同的数据对象,它有不同的方法。我之前说 xlab 和 ylab 没什么不同是对 plot.default 说的,而在 plot.formula 中确实对 ylab 做了特别处理

         methods(plot)
         [1] plot.acf*           plot.data.frame*    plot.decomposed.ts*
         [4] plot.default        plot.dendrogram*    plot.density*      
         [7] plot.ecdf           plot.factor*        plot.formula*      
        [10] plot.function       plot.hclust*        plot.histogram*    
        [13] plot.HoltWinters*   plot.isoreg*        plot.lm*           
        [16] plot.medpolish*     plot.mlm*           plot.ppr*          
        [19] plot.prcomp*        plot.princomp*      plot.profile.nls*  
        [22] plot.raster*        plot.spec*          plot.stepfun       
        [25] plot.stl*           plot.table*         plot.ts            
        [28] plot.tskernel*      plot.TukeyHSD*     
        see '?methods' for accessing help and source code

        Cloud2016 Base R 的源代码说实话不读也罢,它并不适合学习。在 plot.formula 中,我怀疑是这句 do.callylab 从 call 运行为实际值了:https://github.com/wch/r-source/blob/540cb48/src/library/graphics/R/plot.R#L207 因为 do.call() 默认不保护表达式。对比:

        > do.call(c, list(a = substitute(cars[i, 1], list(i = 1))))  # 默认不保护
        a 
        4 
        > do.call(c, list(a = substitute(cars[i, 1], list(i = 1))), quote = TRUE)  # 保护表达式
        $a
        cars[1, 1]

        quote() / enquote() 这些概念比较难理解,我至今也没完全搞明白,也没太大兴趣去深究。

          yihui dapengde 太好了,终于挖出根源了,我觉得这应该算一个 BUG 了,英语水平好的大神们有时间的话,不妨提交一个报告

          yihui
          关于 quote() / enquote(),只知道 enquote() 是表达式再额外加个quote, 例子如下:

          > quote(AA(c(10.5, 15.2, 12.3))) # AA 未定义, 保护表达式
          AA(c(10.5, 15.2, 12.3))
          > enquote(call("AA", c(10.5, 15.2, 12.3))) # 进一步保护表达式?基本上没用过这块。
          quote(AA(c(10.5, 15.2, 12.3)))

          关于 quote()call()的区别,call()不保护 arguments,比如:

          > quote(round(BB)) ## BB未定义,保护所有表达式
          round(BB)
          > call("round", BB) ## 保护 "round", 不保护 BB
          Error: object 'BB' not found
          5 个月 后
          7 个月 后