使用scale_fill_manual重新创建scale_fill_brewer

时间:2015-01-14 09:34:54

标签: r ggplot2

我正在尝试了解包scale_fill_brewer的{​​{1}}和scale_fill_manual之间的关联。

首先,生成一个填充颜色的ggplot:

ggplot2

enter image description here

现在,使用library(ggplot2) p <- ggplot(data = mtcars, aes(x = mpg, y = wt, group = cyl, fill = factor(cyl))) + geom_area(position = 'stack') # apply ready-made palette with scale_fill_brewer from ggplot2 p + scale_fill_brewer(palette = "Blues")

进行复制
scale_fill_manual

其中3是数据中的填充颜色数。为方便起见,我使用了包library(RColorBrewer) p + scale_fill_manual(values = brewer.pal(3, "Blues")) 的{​​{1}}函数。

据我了解,brewer.pal的便利性在于它会自动计算数据中唯一级别的数量(本例中为3)。这是我复制的尝试:

RColorBrewer

我的问题是:scale_fill_brewer如何计算数据中的关卡数量?

我有兴趣了解其他p + scale_fill_manual(values = brewer.pal(length(levels(factor(mtcars$cyl))), "Blues")) 可能正在做什么。如果我将更加用户友好的scale_fill_brewer替换为更加扭曲的fill_color_brewer实现(如上所述),我可能会遇到任何困难。

仔细阅读源代码:

fill_color_brewer

我无法看到scale_fill_manual如何计算数据中唯一级别的数量。也许隐藏在scale_fill_brewer function (..., type = "seq", palette = 1) { discrete_scale("fill", "brewer", brewer_pal(type, palette), ...) }

编辑:函数scale_fill_brewer在哪里接收计算数据中级别数的指令?是在...还是在scale_fill_brewer或其他地方?

"seq"功能错综复杂,我迷路了。以下是其论点:

...

是否有任何计算级别数?

1 个答案:

答案 0 :(得分:3)

最简单的方法是跟踪它是考虑(1)设置绘图数据结构,以及(2)解析美学。它使用S3,因此分支是隐含的

设置调用序列

  1. [scale-brewer.R] scale_fill_brewer(type="seq", palette="Blues")

  2. [scale-.R] discrete_scale(...) - 返回表示比例的对象

  3.   structure(list(
        call = match.call(),
    
        aesthetics = aesthetics,
        scale_name = scale_name,
        palette = palette,
    
        range = DiscreteRange$new(),        ## this is scales::DiscreteRange 
        ...), , class = c(scale_name, "discrete", "scale"))
    

    解析调用序列

    1. [plot-build.R] ggplot_build(plot) - 对于非位置比例,请应用scales_train_df
    2.     # Train and map non-position scales
          npscales <- scales$non_position_scales()       ## scales is plot$scales, S4 type Scales
          if (npscales$n() > 0) {
            lapply(data, scales_train_df, scales = npscales)
            data <- lapply(data, scales_map_df, scales = npscales)
          }
      
      1. [scales-.r] scales_train_df(...) - 再次通过尺度$ scale(列表)进行迭代

      2. [scale-.r] scale_train_df(...) - 再次迭代

      3. [scale-.r] scale_train(...) - S3泛函

      4. [scale-.r] scale_train.discrete(...) - 差不多......

      5.     scale$range$train(x, drop = scale$drop)
        
        1. 但是scale $ range是一个DiscreteRange实例,所以它调用(scales::DiscreteRange$new())$train,它会覆盖scale $ range!
        2.     range <<- train_discrete(x, range, drop)
          
          1. scales:::train_discrete(...) - 再次,差不多......

          2. scales:::discrete_range(...) - 仍然没有......

          3. scales:::clevels(...) - 就在那里!

          4. 到目前为止,scale$range已被因子的级别覆盖。将调用堆栈展开到#1,我们现在调用scales_map_df

            1. [plot-build.R] ggplot_build(plot) - 对于非位置比例,请应用scales_train_df
            2.     # Train and map non-position scales
                  npscales <- scales$non_position_scales()       ## scales is plot$scales, S4 type Scales
                  if (npscales$n() > 0) {
                    lapply(data, scales_train_df, scales = npscales)
                    data <- lapply(data, scales_map_df, scales = npscales)
                  }
              
              1. [scales-.r] scale_maps_df(...) - 迭代

              2. [scale-.r] scale_map_df(...) - iterate

              3. [scale-.r] scale_map.discrete - 填充调色板(非位置刻度!)

                scale_map.discrete&lt; - function(scale,x,limits = scale_limits(scale)){   n&lt; - sum(!is.na(limits))   pal&lt; - scale $ palette(n)   ... }