В ggproto coord $ transform не преобразовал некоторые столбцы в [0, 1]

#r #ggplot2 #ggproto

#r #ggplot2 #ggproto

Вопрос:

Я хочу создать новый геометрический тип: 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
 

для простоты я просто не учитываю цвет панели.

Результирующий график выглядит следующим образом:

скриншот

Я добавил a browser() внутри ggproto функции, и я обнаружил, что coord$transform эстетика не преобразовала op , hi , lo , cl в interverl [0,1] . Как исправить эту проблему?

Кроме того, есть ли какие-либо другие документы о том, как создать свой собственный геометрический тип, кроме статьи Хэдли?

Комментарии:

1. Похоже, что вина transform_position() вызвана функцией in coord$transform . Код показывает, что он преобразует только столбцы в data.frame с именем x and y . Я не знаю решения вашей проблемы, но я бы попытался подумать, нужно ли вам их масштабировать (?).

2. Хотя, если подумать, тот же код также предполагает возможность того, что несколько масштабов могут быть «x» и / или «y». Может быть, там что-то есть?

3. Кроме того, функция ggplot2:::aes_to_scale — это та, которая сопоставляет data.frame имена независимо от того, являются они x или y масштабируются. Посмотрите документацию, которую вам нужно использовать "x", "xmin", "xmax", "xend", "xintercept" , или эквивалентную эстетику для оси y. Это также упоминается в ?transform_position . Я думаю, что если вы сможете найти способ сопоставить свои переменные с этими, вы решите свою проблему.

Ответ №1:

Как упоминалось в комментариях под вопросом OP, проблема заключается aes_to_scale() в функции внутри 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?

Комментарии:

1. Я думаю, вы поняли суть. Я пытаюсь изменить имена столбцов data внутри draw_panel функции с op, hi, lo, cl на y, ymax, ymin, yend . Затем coords$transfrom «знает» преобразовать эти столбцы в [0, 1] .