写一个ggplot2 图层

参考:

ggplot2高级:构建自己的图层
Extending ggplot2
r - 从头开始创建geom / stat
扩展ggplot2:如何构建geom和stat?
编写ggplot自定义几何函数
诹图

前面写道如何添加平均值【ggplot2】 不同情形添加平均值
想用图层来完成。

效果:每一个分组添加最大值最小值水平线

image.png

实践:

Part1.画一个图层,快速画出max,min 水平线

p <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point() +
  facet_wrap(~ cyl)
cdat <- mtcars %>% group_by(cyl) %>% dplyr::summarise(m=mean(wt))
p + geom_hline(data=cdat,aes(yintercept=m))


### 
StatSummaryTest <- ggproto("StatSummaryTest", Stat,
                           required_aes = c("x","y"),
                           
                           compute_group = function(data, scales,params,
                                                    func=mean){
                             x=range(data$x)
                             y=func(data$y)
                             grid=data.frame(x,y)
                           }
                           
)

stat_summary_test <- function(mapping = NULL, data = NULL, geom = "line",
                              position = "identity", na.rm = TRUE, show.legend = NA,
                              inherit.aes = TRUE, func=mean,...){
  layer(
    stat = StatSummaryTest, data = data, mapping = mapping, geom = geom,
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(func=func,na.rm = na.rm, ...)
    
  )
}


ggplot(mtcars, aes(mpg, wt,color=factor(cyl))) +
  geom_point()+
  stat_summary_test(func=max)+
  stat_summary_test(func=min)+
  facet_grid(.~factor(cyl),space = "free",scales = "free")


画出平均值

ggplot(mtcars, aes(mpg, wt,color=factor(cyl))) +
  geom_point()+
  stat_summary_test(func=mean)+
  facet_grid(.~factor(cyl),space = "free",scales = "free")
image.png

Part2.画一个类似地毯图图层(地毯图一般为线条)

文章里面图片风格


image.png
p <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point() +
  facet_wrap(~ cyl)
cdat <- mtcars %>% group_by(cyl) %>% dplyr::summarise(m=mean(wt))
p + geom_hline(data=cdat,aes(yintercept=m))


###
StatRugPoint <- ggproto("StatRugPoint ", Stat,
                        required_aes = c("x","y"),
                        
                        compute_group = function(data, scales,params,
                                                 sides="b"){
                          if(sides=="b"){
                            x=data$x
                            y=-Inf
                          } else if(sides=="t"){
                            x=data$x
                            y=Inf
                          } else if(sides=="l"){
                            x=-Inf
                            y=data$y
                          } else if (sides=="r"){
                            x=Inf
                            y=data$y
                          } else {
                            print("check inpur type")
                          }
                          
                          grid=data.frame(x,y)
                        }
                        
)

stat_rug_point <- function(mapping = NULL, data = NULL, geom = "point",
                           position = "identity", na.rm = TRUE, show.legend = NA,
                           inherit.aes = TRUE, sides="b",...){
  layer(
    stat = StatRugPoint, data = data, mapping = mapping, geom = geom,
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(sides=sides,na.rm = na.rm, ...)
    
  )
}


ggplot(mtcars, aes(mpg, wt,color=factor(cyl))) +
  geom_point()+
  stat_rug_point(sides="b",size=4,alpha=I(0.5))

# ggplot(mtcars, aes(mpg, wt,color=mpg)) +
# geom_point()+
#   stat_rug_point(sides ="b",size=4)
image.png

Part3. 模仿geom_rug 代码

主要segmentGrod 变成circleGrod,有些参数没有delete 。

library(grid)
geom_rug2 <- function(mapping = NULL, data = NULL,
                     stat = "identity", position = "identity",
                     ...,
                     outside = FALSE,
                     sides = "bl",
                     length = unit(0.03, "npc"),
                     na.rm = FALSE,
                     show.legend = NA,
                     inherit.aes = TRUE) {
  layer(
    data = data,
    mapping = mapping,
    stat = stat,
    geom = GeomRug2 ,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      outside = outside,
      sides = sides,
      length = length,
      na.rm = na.rm,
      ...
    )
  )
}


#' @rdname ggplot2-ggproto
#' @format NULL
#' @usage NULL
#' @export
GeomRug2 <- ggproto("GeomRug2", Geom,
                   optional_aes = c("x", "y"),
                   
                   draw_panel = function(data, panel_params, coord, sides = "bl", outside = FALSE, length = unit(0.03, "npc")) {
                     if (!inherits(length, "unit")) {
                       abort("'length' must be a 'unit' object.")
                     }
                     rugs <- list()
                     data <- coord$transform(data, panel_params)
                     
                     # For coord_flip, coord$tranform does not flip the sides where to
                     # draw the rugs. We have to flip them.
                     if (inherits(coord, 'CoordFlip')) {
                       sides <- chartr('tblr', 'rlbt', sides)
                     }
                     
                     # move the rug to outside the main plot space
                     rug_length <- if (!outside) {
                       list(min = length, max = unit(1, "npc") - length)
                     } else {
                       list(min = -1 * length, max = unit(1, "npc") + length)
                     }
                     
                     gp <- gpar(fill= data$fill,col = alpha(data$colour, data$alpha), size=data$size)
                     
                     if (!is.null(data$x)) {
                       if (grepl("b", sides)) {
                         rugs$x_b <- circleGrob(
                           x = unit(data$x, "native"),
                           y = unit(0, "npc")+ rug_length$min,
                           r = rug_length$min,
                           
                           gp = gp
                         )
                       }
                       
                       if (grepl("t", sides)) {
                         rugs$x_t <- circleGrob(
                           x = unit(data$x, "native"),
                           y = unit(1, "npc")- rug_length$max,
                           r = rug_length$max,
                           gp = gp
                         )
                       }
                     }
                     
                     if (!is.null(data$y)) {
                       if (grepl("l", sides)) {
                         rugs$y_l <- circleGrob(
                           y = unit(data$y, "native"),
                           x = rug_length$min ,
                           r = rug_length$min ,
                           gp = gp
                         )
                       }
                       
                       if (grepl("r", sides)) {
                         rugs$y_r <- circleGrob(
                           y = unit(data$y, "native"),
                           x0 = rug_length$max ,
                           r = rug_length$max ,
                           gp = gp
                         )
                       }
                     }
                     
                     gTree(children = do.call("gList", rugs))
                   },
                   
                   default_aes = aes(colour = "black", size = 0.1, linetype = 1, alpha = NA),
                   
                   draw_key = draw_key_path
)



ggplot(mtcars, aes(mpg, wt,color=mpg)) +
  geom_point()+
  geom_rug2(length = unit(0.01, "npc"))

# ggplot(mtcars, aes(mpg, wt,color=factor(cyl))) +
#   geom_point()+
#   stat_rug_point(sides="b",size=4,alpha=I(0.5))

image.png

思考:

1.尝试 Part2 时候,发现了一个bug, 颜色只能是factor ,对于梯度颜色,地毯图点为黑色,有点没搞清楚。
2.尝试Part3,模仿geom_rug 脚本就行修改,也发现不完善地方,地毯图填充颜色是个固定值,可能是par() 参数有些问题。后面学习深入了,再进行修改吧~

欢迎评论交流~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352