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

Cloud2016 深究起来好累。而且好像还没有回答为啥 xlab 和 ylab 区别对待的问题。你要不要提交这个 bug 给 R?

    dapengde 深究起来,我觉得不是 BUG, xlab 和 ylab 也没有区别对待,只是我传递给它一个它也不知道怎么处理的 R 对象 call 所以它就随便处理了,随便的意思就是不知道会有什么后果的处理!试着call @yihui 应该会有答案

      Cloud2016 如果是随便处理的话,那 xlab 应该有一半几率适合方法1,一半几率方法2。此前我画了好几次,好像挺稳定的。要不画100次试试?我现在手头没电脑……

        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 个月 后