用自己的几何图形扩展ggplot:调整默认比例

时间:2019-04-01 14:43:09

标签: r ggplot2 ggproto

背景

在阅读this beautiful answer on how to extend ggplotthe corresponding vignette之后,我试图理解如何扩展ggplot

简而言之

我知道这些零件是如何组合在一起的,但是我缺少一个重要的信息:ggplot如何确定轴的默认范围?

代码

考虑以下玩具示例:

library(grid)
library(ggplot2)

GeomFit <- ggproto("GeomFit", GeomBar,
                   required_aes = c("x", "y"),
                   setup_data = .subset2(GeomBar, "setup_data"),
                   draw_panel = function(self, data, panel_scales, coord, width = NULL) {
                     bars <- ggproto_parent(GeomBar, self)$draw_panel(data,
                                                                      panel_scales, 
                                                                      coord)
                     coords <- coord$transform(data, panel_scales)    
                     tg <- textGrob("test", coords$x, coords$y * 2 - coords$ymin)
                     grobTree(bars, tg)
                   }
)

geom_fit <- function(mapping = NULL, data = NULL,
                     stat = "count", position = "stack",
                     ...,
                     width = NULL,
                     binwidth = NULL,
                     na.rm = FALSE,
                     show.legend = NA,
                     inherit.aes = TRUE) {

  layer(
    data = data,
    mapping = mapping,
    stat = stat,
    geom = GeomFit,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      width = width,
      na.rm = na.rm,
      ...
    )
  )
}

set.seed(1234567)
data_gd <- data.frame(x = letters[1:5], 
                      y = 1:5)

p <- ggplot(data = data_gd, aes(x = x, y = y, fill = x)) + 
  geom_fit(stat = "identity")

哪个产生以下情节: Barplot with text

问题

如您所见,某些文本未显示。我假设ggplot以某种方式计算了轴的范围,因为它不知道我的textGrob所需的额外空间。我该如何解决? (所需结果等同于p + expand_limits(y = 10)

NB。当然,可以通过要求添加手动刻度来将问题推给最终用户。但理想情况下,我希望比例尺正确设置。

1 个答案:

答案 0 :(得分:2)

尤里卡

由于@ Z.Lin在调试<td class="full" width="300px" style="width: 300px;"> <table> <td background="http://www.gstatic.com/tv/thumb/persons/8327/8327_v9_bb.jpg" width="200" height="200" bgcolor="#7bceeb" valign="top"> <tr> <table cellpadding="0" cellspacing="0" border="0" width="100%"> <tr> <!--[if gte mso 9]> <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="mso-width-percent:1000; width: 200px; height: 200px;"> <v:fill type="tile" src="http://www.gstatic.com/tv/thumb/persons/8327/8327_v9_bb.jpg" color="#7bceeb" /> <v:textbox style="mso-fit-shape-to-text:true" inset="0,0,0,0"> <![endif]--> <div style="width: 200px; height: 200px;"> </div> <!--[if gte mso 9]> </v:textbox> </v:rect> <![endif]--> </td> </tr> </table> </tr> <table> 代码方面的出色帮助,发现了一个丑陋的骇客。这是我想到的这个丑陋的技巧,以供将来参考:

我怎么到达那里

在调试ggplot时,我了解到罪魁祸首可以在debug(ggplot2:::ggplot_build.ggplot)中的某个地方找到(在我的情节中,  FacetNull$train_scales之类的其他方面也类似地工作)。我是通过FacetGrid学到的,而我依次是在answer by Z.Lin in another thread学到的。

一旦我能够调试debug(environment(FacetNull$train_scales)$f)对象,我就能看到在此功能中秤已经过训练。基本上,该功能着眼于与特定比例相关的美学(不知道首先在何处设置此信息,是否有任何想法?),并查看层数据中存在哪些美学。

我看到一个字段ggproto(根据this table-仅用于ymax_final)是设置秤所考虑的字段之一。借助这些信息,可以通过将stat_boxplot中的该字段设置为适当的值来轻松找到难看的骇客。

代码

setup_data

结果

Barplot with labels

悬而未决的问题

如果不手动定义(轴)刻度,该在哪里设置?我猜这里已经设置了与缩放相关的字段。