5

我想创建一个新的 Geom 类型:geom_ohlc(),类似于烛台图,用于绘制股票开盘价高低收盘数据。

在学习了这篇哈德利的文章之后:我试过这个:

GeomOHLC <- ggproto(`_class` = "GeomOHLC", `_inherit` = Geom,

                 required_aes = c("x", "op", "hi", "lo", "cl"),

                 draw_panel = function(data, panel_scales, coord){

                   coords <- coord$transform(data, panel_scales)
                   browser() # <<-- here is where I found the problem
                   grid::gList(
                     grid::rectGrob(
                       x = coords$x,
                       y = pmin(coords$op, coords$cl),
                       vjust = 0,
                       width = 0.01,
                       height = abs(coords$op - coords$cl),
                       gp = grid::gpar(col = coords$color, fill = "yellow")
                     ),
                     grid::segmentsGrob(
                       x0 = coords$x,
                       y0 = coords$lo,
                       x1 = coords$x,
                       y1 = coords$hi
                       )
                   )
                 })
    geom_ohlc <- function(data = NULL, mapping = NULL, stat = "identity", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ...)
    {
      layer(
        geom = GeomOHLC, mapping = mapping, data = data, 
        stat = stat, position = position, show.legend = show.legend, 
        inherit.aes = inherit.aes, params = list(na.rm = na.rm, ...)
      )
    }   
    dt <- data.table(x = 1:10, open = 1:10, high = 3:12, low = 0:9, close = 2:11)
    p <- ggplot(dt, aes(x = x, op = open, hi = high, lo = low, cl = close)) + 
      geom_ohlc() 
    p

为简单起见,我只是不考虑条的颜色。

结果图是这样的:

截屏

browser()我在函数内部添加了一个ggproto,我发现coord$transform并没有将op, hi, lo,cl美学转换为 interverl [0,1]。如何解决这个问题?

此外,除了 Hadley 的文章之外,还有其他关于如何创建自己的 Geom 类型的文档吗?

4

1 回答 1

2

正如 OP 问题下的评论中所述,问题出在aes_to_scale()function inside transform_position(),而后者又由coord$transform. 转换仅限于命名的变量x, xmin, xmax, xend, xintercept和 y 轴的等效项。这在 transform_position 的帮助中提到:

描述

转换所有位置变量的便利功能。

用法

transform_position(df, trans_x = NULL, trans_y = NULL, ...) 参数

trans_x, trans_y x 和 y 美学的变换函数。(将转换 x、xmin、xmax、xend 等)... 传递给 trans_x 和 trans_y 的附加参数。

一种解决方法是使用这些变量名而不是 OP 使用的变量名。以下代码用于转换变量,但在其他地方失败(见最后)。我不知道预期情节的细节,所以没有尝试修复这个错误。

GeomOHLC <- ggproto(
  `_class` = "GeomOHLC",
  `_inherit` = Geom,

  required_aes = c("x", "yintercept", "ymin", "ymax", "yend"),

  draw_panel = function(data, panel_scales, coord) {
    coords <- coord$transform(data, panel_scales)
    #browser() # <<-- here is where I found the problem
    grid::gList(
      grid::rectGrob(
        x = coords$x,
        y = pmin(coords$yintercept, coords$yend),
        vjust = 0,
        width = 0.01,
        height = abs(coords$op - coords$cl),
        gp = grid::gpar(col = coords$color, fill = "yellow")
      ),
      grid::segmentsGrob(
        x0 = coords$x,
        y0 = coords$ymin,
        x1 = coords$x,
        y1 = coords$ymax
      )
    )
  }
)
geom_ohlc <-
  function(data = NULL,
           mapping = NULL,
           stat = "identity",
           position = "identity",
           na.rm = FALSE,
           show.legend = NA,
           inherit.aes = TRUE,
           ...)
  {
    layer(
      geom = GeomOHLC,
      mapping = mapping,
      data = data,
      stat = stat,
      position = position,
      show.legend = show.legend,
      inherit.aes = inherit.aes,
      params = list(na.rm = na.rm, ...)
    )
  }
dt <-
  data.table(
    x = 1:10,
    open = 1:10,
    high = 3:12,
    low = 0:9,
    close = 2:11
  )
p <-
  ggplot(dt, aes(
    x = x,
    yintercept = open,
    ymin = high,
    ymax = low,
    yend = close
  )) +
  geom_ohlc()
p

这会转换变量,但会产生以下错误:

Error in unit(height, default.units) : 
  'x' and 'units' must have length > 0 

但希望从这里它可以工作。

注意:我相当随意地选择了原始变量名称(op、hi、lo、cl)之间的映射。特别yintercept好像不太合适。也许需要在 ggplot2 中支持任意比例变量名称?

于 2016-10-16T15:19:49.510 回答