R生信修炼

Writing ggplot2 extensions

2019-12-23  本文已影响0人  吴十三和小可爱的札记

New themes

新的themes 是最简单的扩展套件,基本上就是ggplot2 的theme的参数叠加,需要注意的是参数: complete = TRUE。

print(theme_grey):从0开始构建新的theme(所需参数非常多)。

print(theme_bw):以theme_grey 为基础,通过%+replace%替换theme_grey 中的一些参数,形成新的主题。

function (base_size = 11, base_family = "", base_line_size = base_size/22, base_rect_size = base_size/22) 
{
 theme_grey(base_size = base_size, base_family = base_family, base_line_size = base_line_size, base_rect_size = base_rect_size) %+replace% 
 theme(panel.background = element_rect(fill = "white", 
 colour = NA), panel.border = element_rect(fill = NA, 
 colour = "grey20"), panel.grid = element_line(colour = "grey92"), 
 panel.grid.minor = element_line(size = rel(0.5)), 
 strip.background = element_rect(fill = "grey85", 
 colour = "grey20"), legend.key = element_rect(fill = "white", 
 colour = NA), complete = TRUE)
}

print(theme_minimal):以theme_bw 为基础,修改一些关键点生成。

ggplot2-ggproto

ggproto 是一个基于原型的OO( object-oriented)系统,该系统灵感源于proto包。它模糊了类和实例(classes and instances)之间的界限,干净利落地支持跨包继承(Inherits),使之具有更快的性能。所有ggplot2对象都是使用ggproto 系统构建的,它维护了ggplot2 所需的proto features。换句话说,如果需要创建新的统计Stat、Geom、Position、Scale或者主题系统,就需要了解ggproto 这个OO system

Person <- ggproto("Person", NULL,
 first = "",
 last = "",
 birthdate = NA,

 full_name = function(self) {
 paste(self$first, self$last)
 },
 age = function(self) {
 days_old <- Sys.Date() - self$birthdate
 floor(as.integer(days_old) / 365.25)
 },
 description = function(self) {
 paste(self$full_name(), "is", self$age(), "old")
 }
)

在这个ggproto 系统中,"Person"是该ggproto对象的class name,NULL 表示没有父对象(从0开始创建),接着是一系列参数和function。参数self 为 function 提供实施目标,而function 的运行的输出结果也能被self 参数用调用。

Me <- ggproto(NULL, Person,
 first = "Thomas Lin",
 last = "Pedersen",
 birthdate = as.Date("1985/10/12")
)

此时,ggproto对象Me继承自Person 对象,Me 里面的参数可以调用Person 对象的function。

Me$description()
# "Thomas Lin Pedersen is 34 old"
​
Me$full_name()
#"Thomas Lin Pedersen"
​
Me$birthdate
"1985-10-12"

延伸阅读,ggproto_parent() function。

ggplot2 中的ggproto 系统是stateless的,换句话说,ggproto类别对象建立后就是稳定不变的,它们类似于量产的零件,我们在ggplot2 基础上进行构建时,只需要调用不同的零件就行了。

例如,在创建GeomErrorbar这个系统时,调用或者继承了GeomLinerange中的setup_params。

GeomErrorbar <- ggproto(
 # ...
 setup_params = function(data, params) {
 GeomLinerange$setup_params(data, params)
 }
 # ...
}

一般来说,如果需要创建一个新的ggplot2的统计变换(stat),只需要创建一个ggproto,并申明它继承(Inherits)于Stat就可以了,如ggproto("StatChull", Stat...)。创建新的geom也一样:ggproto("GeomSimplePoint", Geom...)。

创建新的stat

Stat 主要封装了compute_layer(), compute_panel(), and compute_group()等一连串的call 。一般来说,compute_layer() 通过compute_panel() 中的panel 分割纵列,而compute_panel() 通过compute_group() 中的group 分割数据纵列,最终将计算结果重新组装。

setup_params() 接受构建layer data时规定的参数,返回的是一个参数名与compute_中的参数名相同的参数 list,用于设定需要计算的数据和参数信息。当setup_params() 设定后,setup_data() 会运行一次,用于接受修改好的layer data,返回的是一个layer data。

StatChull <- ggproto("StatChull", Stat,
 required_aes = c("x", "y"),
 compute_group = function(data, scales) {
 data[chull(data$x, data$y), , drop = FALSE]
 }
)

上面的代码创建了一个简单的stat,前两个参数是它的名字和来源(继承自什么,Stat—也是一个ggproto系统),第三个是需要的美学参数(需要做统计变换的列),第四个是统计变换。data就是data frame, scales 是包含x,y的scales。chull(){grDevices} 函数返回位于凸壳位置的点的列索引,索引按顺时针方向排列;drop将数据降低一个维度(data.frame — list)。

<setup_params() 接受构建layer data时规定的参数,返回的是一个参数名与compute_中的参数名相同的参数 list。

setup_data() 接受修改好的layer data,返回的是一个layer data。

layer可以用list包起来,一次可以添加多个layer>

上一篇 下一篇

猜你喜欢

热点阅读