如何从已知的ggplot对象中提取颜色等信息?

最近在使用一些包装好的作图函数绘图,如TCseq包中的timeclustplot函数,尽管这些函数可以满足大部分的需求,但是如果想做个性化的修饰的时候,需要自己使用ggplot2重新画。由于自己审美过于直男,因此配色方面过丑是个大问题。因此希望在绘图的时候能使用包装函数中的配色方案。这就涉及到本文的讨论的问题,如何从别人已经做好的ggplot对象中提取映射的颜色信息?
首先我们需要确认操作的对象是ggplot对象

> class(tcaplot_patient1[[1]])
[1] "gg"     "ggplot"

其次需要查看ggplot对象中的基本的组织形式,来尝试寻找颜色信息存储的位置

> str(tcaplot_patient1[[1]],max.level = 2)
List of 10
 $ data       :'data.frame':    7630 obs. of  4 variables:
  ..$ group     : Factor w/ 545 levels "EFNA2","PLAUR",..: 1 1 1 1 1 1 1 1 1 1 ...
  ..$ time      : Factor w/ 14 levels "patient1_ctl",..: 12 4 10 1 7 9 13 2 8 14 ...
  ..$ value     : num [1:7630] 0.765 -1.263 -0.13 0.839 -0.997 ...
  ..$ membership: num [1:7630] 0.25 0.25 0.25 0.25 0.25 ...
 $ layers     :List of 1
  ..$ :Classes 'LayerInstance', 'Layer', 'ggproto', 'gg' 
    aes_params: list
    compute_aesthetics: function
    compute_geom_1: function
    compute_geom_2: function
    compute_position: function
    compute_statistic: function
    data: waiver
    draw_geom: function
    finish_statistics: function
    geom: 
        aesthetics: function
        default_aes: uneval
        draw_group: function
        draw_key: function
        draw_layer: function
        draw_panel: function
        extra_params: na.rm
        handle_na: function
        non_missing_aes: 
        optional_aes: 
        parameters: function
        required_aes: x y
        setup_data: function
        use_defaults: function
        super:  
    geom_params: list
    inherit.aes: TRUE
    layer_data: function
    map_statistic: function
    mapping: uneval
    position: 
        compute_layer: function
        compute_panel: function
        required_aes: 
        setup_data: function
        setup_params: function
        super:  
    print: function
    setup_layer: function
    show.legend: NA
    stat: 
        aesthetics: function
        compute_group: function
        compute_layer: function
        compute_panel: function
        default_aes: uneval
        extra_params: na.rm
        finish_layer: function
        non_missing_aes: 
        parameters: function
        required_aes: 
        retransform: TRUE
        setup_data: function
        setup_params: function
        super:  
    stat_params: list
    super:   
 $ scales     :Classes 'ScalesList', 'ggproto', 'gg' 
    add: function
    clone: function
    find: function
    get_scales: function
    has_scale: function
    input: function
    n: function
    non_position_scales: function
    scales: list
    super:   
 $ mapping    :List of 3
  ..$ x     : language ~time
  .. ..- attr(*, ".Environment")= 
  ..$ y     : language ~value
  .. ..- attr(*, ".Environment")= 
  ..$ colour: language ~membership
  .. ..- attr(*, ".Environment")= 
  ..- attr(*, "class")= chr "uneval"
 $ theme      :List of 67
  ..$ line                      :List of 6
  .. ..- attr(*, "class")= chr [1:2] "element_line" "element"
  ..$ rect                      :List of 5
  .. ..- attr(*, "class")= chr [1:2] "element_rect" "element"
  ..$ text                      :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.title                :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.title.x              :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.title.x.top          :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.title.y              :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.title.y.right        :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.text                 :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.text.x               :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.text.x.top           :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.text.y               :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.text.y.right         :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ axis.ticks                :List of 6
  .. ..- attr(*, "class")= chr [1:2] "element_line" "element"
  ..$ axis.ticks.length         : 'unit' num 2.75pt
  .. ..- attr(*, "valid.unit")= int 8
  .. ..- attr(*, "unit")= chr "pt"
  ..$ axis.ticks.length.x       : NULL
  ..$ axis.ticks.length.x.top   : NULL
  ..$ axis.ticks.length.x.bottom: NULL
  ..$ axis.ticks.length.y       : NULL
  ..$ axis.ticks.length.y.left  : NULL
  ..$ axis.ticks.length.y.right : NULL
  ..$ axis.line                 : list()
  .. ..- attr(*, "class")= chr [1:2] "element_blank" "element"
  ..$ axis.line.x               :List of 6
  .. ..- attr(*, "class")= chr [1:2] "element_line" "element"
  ..$ axis.line.y               :List of 6
  .. ..- attr(*, "class")= chr [1:2] "element_line" "element"
  ..$ legend.background         :List of 5
  .. ..- attr(*, "class")= chr [1:2] "element_rect" "element"
  ..$ legend.margin             : 'margin' num [1:4] 5.5pt 5.5pt 5.5pt 5.5pt
  .. ..- attr(*, "valid.unit")= int 8
  .. ..- attr(*, "unit")= chr "pt"
  ..$ legend.spacing            : 'unit' num 11pt
  .. ..- attr(*, "valid.unit")= int 8
  .. ..- attr(*, "unit")= chr "pt"
  ..$ legend.spacing.x          : NULL
  ..$ legend.spacing.y          : NULL
  ..$ legend.key                :List of 5
  .. ..- attr(*, "class")= chr [1:2] "element_rect" "element"
  ..$ legend.key.size           : 'unit' num 1.2lines
  .. ..- attr(*, "valid.unit")= int 3
  .. ..- attr(*, "unit")= chr "lines"
  ..$ legend.key.height         : NULL
  ..$ legend.key.width          : NULL
  ..$ legend.text               :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ legend.text.align         : NULL
  ..$ legend.title              :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ legend.title.align        : NULL
  ..$ legend.position           : chr "right"
  ..$ legend.direction          : NULL
  ..$ legend.justification      : chr "center"
  ..$ legend.box                : NULL
  ..$ legend.box.margin         : 'margin' num [1:4] 0cm 0cm 0cm 0cm
  .. ..- attr(*, "valid.unit")= int 1
  .. ..- attr(*, "unit")= chr "cm"
  ..$ legend.box.background     : list()
  .. ..- attr(*, "class")= chr [1:2] "element_blank" "element"
  ..$ legend.box.spacing        : 'unit' num 11pt
  .. ..- attr(*, "valid.unit")= int 8
  .. ..- attr(*, "unit")= chr "pt"
  ..$ panel.background          :List of 5
  .. ..- attr(*, "class")= chr [1:2] "element_rect" "element"
  ..$ panel.border              : list()
  .. ..- attr(*, "class")= chr [1:2] "element_blank" "element"
  ..$ panel.spacing             : 'unit' num 5.5pt
  .. ..- attr(*, "valid.unit")= int 8
  .. ..- attr(*, "unit")= chr "pt"
  ..$ panel.spacing.x           : NULL
  ..$ panel.spacing.y           : NULL
  ..$ panel.grid                :List of 6
  .. ..- attr(*, "class")= chr [1:2] "element_line" "element"
  ..$ panel.grid.major          : list()
  .. ..- attr(*, "class")= chr [1:2] "element_blank" "element"
  ..$ panel.grid.minor          : list()
  .. ..- attr(*, "class")= chr [1:2] "element_blank" "element"
  ..$ panel.ontop               : logi FALSE
  ..$ plot.background           :List of 5
  .. ..- attr(*, "class")= chr [1:2] "element_rect" "element"
  ..$ plot.title                :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ plot.subtitle             :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ plot.caption              :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ plot.tag                  :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ plot.tag.position         : chr "topleft"
  ..$ plot.margin               : 'margin' num [1:4] 5.5pt 5.5pt 5.5pt 5.5pt
  .. ..- attr(*, "valid.unit")= int 8
  .. ..- attr(*, "unit")= chr "pt"
  ..$ strip.background          :List of 5
  .. ..- attr(*, "class")= chr [1:2] "element_rect" "element"
  ..$ strip.placement           : chr "inside"
  ..$ strip.text                :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ strip.text.x              : NULL
  ..$ strip.text.y              :List of 11
  .. ..- attr(*, "class")= chr [1:2] "element_text" "element"
  ..$ strip.switch.pad.grid     : 'unit' num 2.75pt
  .. ..- attr(*, "valid.unit")= int 8
  .. ..- attr(*, "unit")= chr "pt"
  ..$ strip.switch.pad.wrap     : 'unit' num 2.75pt
  .. ..- attr(*, "valid.unit")= int 8
  .. ..- attr(*, "unit")= chr "pt"
  ..- attr(*, "class")= chr [1:2] "theme" "gg"
  ..- attr(*, "complete")= logi TRUE
  ..- attr(*, "validate")= logi TRUE
 $ coordinates:Classes 'CoordCartesian', 'Coord', 'ggproto', 'gg' 
    aspect: function
    backtransform_range: function
    clip: on
    default: TRUE
    distance: function
    expand: TRUE
    is_free: function
    is_linear: function
    labels: function
    limits: list
    modify_scales: function
    range: function
    render_axis_h: function
    render_axis_v: function
    render_bg: function
    render_fg: function
    setup_data: function
    setup_layout: function
    setup_panel_params: function
    setup_params: function
    transform: function
    super:   
 $ facet      :Classes 'FacetNull', 'Facet', 'ggproto', 'gg' 
    compute_layout: function
    draw_back: function
    draw_front: function
    draw_labels: function
    draw_panels: function
    finish_data: function
    init_scales: function
    map_data: function
    params: list
    setup_data: function
    setup_params: function
    shrink: TRUE
    train_scales: function
    vars: function
    super:   
 $ plot_env   : 
 $ labels     :List of 5
  ..$ x     : chr "timepoint"
  ..$ y     : chr "expression"
  ..$ title : chr "Cluster 1"
  ..$ colour: chr "membership"
  ..$ group : chr "group"
 $ guides     :List of 1
  ..$ colour:List of 28
  .. ..- attr(*, "class")= chr [1:2] "guide" "colorbar"
 - attr(*, "class")= chr [1:2] "gg" "ggplot"

显然,从ggplot的数据结构中,我们并不能得到什么有用的信息,唯一可能储存颜色信息的scales中也只是一些包装的函数信息,显然这个方法并行不通。
在查阅ggplot官网时发现,ggplot提供了ggplot_build,方便用户提取ggplot对象中有关渲染的信息
链接:https://ggplot2.tidyverse.org/reference/ggplot_build.html
并有如下描述

[ggplot_build()](https://ggplot2.tidyverse.org/reference/ggplot_build.html) takes the plot object, and performs all steps necessary to produce an object that can be rendered. This function outputs two pieces: a list of data frames (one for each layer), and a panel object, which contain all information about axis limits, breaks etc
所以我们可以使用这个函数来提取其中的信息

x<-ggplot_build(tcaplot_patient1[[1]])

其中与颜色相关的信息时保存在data slot里面,如果该图是离散型数据,那只需要对颜色进行unique即可得到所有的颜色代码,如果是连续型数据,可以使用scales包中的show_cols函数来进行挑选

#
m<-cbind(m$data[[1]],m$plot$membership
m<-m[order(m$`m$plot$data$membership`),]
m$colour<-as.factor(m$colour)
m$colour<-factor(m$colour,levels = unique(m$colour))
show_col(levels(m$colour),labels=F)
image.png

你可能感兴趣的:(如何从已知的ggplot对象中提取颜色等信息?)