#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()
вызвана функцией incoord$transform
. Код показывает, что он преобразует только столбцы в data.frame с именемx
andy
. Я не знаю решения вашей проблемы, но я бы попытался подумать, нужно ли вам их масштабировать (?).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] .