【问题标题】:Passing an extra parameter to a custom geom in ggplot2将额外参数传递给 ggplot2 中的自定义几何图形
【发布时间】:2019-07-17 08:55:57
【问题描述】:

我正在创建一个自定义几何图形,并希望它采用一个额外的参数,称为showpoints,它对实际绘图有一些作用。例如,通过将其设置为 FALSE,geom 实际上会返回一个zeroGrob()。我找到了一种方法,但是(i)它笨重而且有些奇怪,并且(ii)我不完全理解我在做什么,这是一个不好的迹象。问题是当你定义一个新的stat时,可​​以运行setup_params,但是geoms没有:

与 Stat 和 Position 相比,Geom 有点不同,因为 设置和计算功能的执行是分开的。设置数据 在位置调整之前运行,draw_layer 直到 渲染时间,很久以后。这意味着没有 setup_params 因为 很难传达这些变化。

[Source]

基本上,我的代码可以使用附加参数来抑制点的绘制:

# draw the points by default
ggplot(mpg, aes(displ, hwy)) + geom_simple_point()

# suppresses drawing of the points
ggplot(mpg, aes(displ, hwy)) + geom_simple_point(showpoints=FALSE)

这是我目前的代码,基于extending ggplot2 tutorial

## Return the grob to draw. The additional parameter,
## showpoints, determines whether a points grob should be returned,
## or whether zeroGrob() should take care of not showing the points
.draw_panel_func <- function(data, panel_params, coord) {
  coords <- coord$transform(data, panel_params)
  showpoints <- unique(data$showpoints)
  cat("showpoints=", as.character(showpoints), "\n")
  if(!is.null(showpoints) && is.logical(showpoints) && !showpoints) {
    return(zeroGrob())
  } else {
    return(
      grid::pointsGrob(coords$x, coords$y,
        pch = coords$shape,
        gp = grid::gpar(col = coords$colour))
   )
 }
}

## definition of the new geom. setup_data inserts the parameter 
## into data, therefore making it accessible for .draw_panel_func
GeomSimplePoint <- ggproto("GeomSimplePoint", Geom,
  required_aes = c("x", "y"),
  default_aes = aes(shape = 19, colour = "black"),
  draw_key = draw_key_point,
  setup_data = function(data, params) {
    if(!is.null(params$showpoints)) {
      data$showpoints <- params$showpoints
    }
    data
  },
  extra_params = c("na.rm", "showpoints"),
  draw_panel = .draw_panel_func
)

geom_simple_point <- function(mapping = NULL, data = NULL, stat = "identity",
                              position = "identity", na.rm = FALSE, show.legend = NA, 
                              inherit.aes = TRUE, showpoints=TRUE, ...) {
  layer(
    geom = GeomSimplePoint, mapping = mapping,  data = data, stat = stat, 
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, showpoints=showpoints, ...)
  )
}

有没有一种更简单的方法可以将选定的额外参数传递给 geom?如果我可以定义extra_params,为什么不能更轻松地访问它们?

【问题讨论】:

    标签: r ggplot2 ggproto


    【解决方案1】:

    有一个比较简单的方法,就是将额外的参数作为参数传递给面板绘制函数。这是一个适用于您的geom_simple_point() 的简单示例:

    GeomSimplePoint <- ggproto(
      "GeomSimplePoint", 
      GeomPoint,
      extra_params = c("na.rm", "showpoints"),
      draw_panel = function(data, panel_params, 
                            coord, na.rm = FALSE, showpoints = TRUE) {
        if (showpoints) {
          return(GeomPoint$draw_panel(data, panel_params, coord, na.rm = na.rm))
        } else {
          return(zeroGrob())
        }
      }
    )
    

    顺便说一句,如果你想复制一个已经存在的 geom 的行为,比如geom_point(),设置你自己的 ggproto 对象来继承那个 geom 的 ggproto 对象会更容易。这样一来,您在 ggproto 中指定的默认 aes、必需 aes 和其他参数会自动从该 geom 复制/继承,您不必手动指定所有这些参数。

    【讨论】:

    • 可能有点跑题了,但是否也可以根据额外的参数从两个不同的geom_* ggproto 对象继承(例如,这里是showpoints)。比方说画一条线或点?
    • 我认为这在技术上是不可能的。但是您可以根据额外的参数使用GeomPoint$draw_panel()GeomPath$draw_panel() 进行切换。不过,您需要确保拥有这些不同方法所需的所有列和参数。
    • 谢谢,这行得通!直到我想根据额外参数指定不同的default_aes。另一种方法是在自定义geom_*(例如geom_simple_point)中调用GeomPointGeomPath。然而,这种方法在等效的自定义stat_* 方法中失败,因为这里ggplot2:::check_subclass 检测到geom_simple_pointGeomPointGeomPath 的命名差异。主题可能值得提出一个新问题;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    • 2018-10-07
    • 1970-01-01
    相关资源
    最近更新 更多