Я нахожусь на ранних этапах изучения того, как расширять ggplot2
. Я хочу создать собственный geom
и связанный stat
. Моей отправной точкой была виньетка. Кроме того, мне помогли это и это. Я пытаюсь составить шаблон, чтобы научить себя и, надеюсь, других.
Главный вопрос:
Внутри моей функции calculate_shadows()
необходимый параметр params$anchor
равен NULL
. Как я могу получить к нему доступ?
Описанная ниже цель предназначена исключительно для изучения того, как создавать собственные stat
и geom
функции, это не настоящая цель: как вы можете видеть на снимках экрана, я знаю, как использовать возможности ggplot2
для построения графиков.
geom
будет считывать данные, а для предоставленных переменных("x", "y")
построит график (за отсутствием лучшего слова)shadows
: горизонтальная линияmin(x)--max(x)
по умолчаниюy=0
и вертикальная линияmin(y)--max(y)
по умолчаниюx=0
. Если имеется опция, эти «якоря» можно изменить, например если пользователь предоставляетx = 35, y = 1
, горизонтальная линия будет нарисована в точке пересеченияy = 1
, а вертикальная линия будет нарисована в точке пересеченияx = 35
. Использование:library(ggplot2) ggplot(data = mtcars, aes(x = mpg, y = wt)) + geom_point() + geom_shadows(x = 35, y = 1)
stat
прочитает данные и для предоставленных переменных("x", "y")
вычислитshadows
в соответствии со значениемstat
. Например, при передачеstat = "identity"
тени будут вычисляться для минимума и максимума данных (как это делаетgeom_shadows
). Но при передачеstat = "quartile"
тени будут вычисляться для первого и третьего квартилей. В более общем плане можно передать функцию типаstats::quantile
с аргументамиargs = list(probs = c(0.10, 0.90), type = 6)
для вычисления теней с использованием 10-го и 90-го процентилей и метода квантилей типа 6. Использование:ggplot(data = mtcars, aes(x = mpg, y = wt)) + geom_point() + stat_shadows(stat = "quartile")
К сожалению, недостаточное знакомство с расширением ggplot2
помешало мне достичь моей цели. Эти сюжеты были «сфальсифицированы» с помощью geom_segment
. Основываясь на руководстве и обсуждениях, упомянутых выше, и изучая существующий код, например stat-qq
или stat-smooth
, я собрал базовую архитектуру для этой цели. Там должно быть много ошибок, буду благодарен за руководство. Также обратите внимание, что подойдет любой из этих подходов: geom_shadows(anchor = c(35, 1))
или geom_shadows(x = 35, y = 1)
.
Теперь вот мои старания. Во-первых, geom-shadows.r
, чтобы определить geom_shadows()
. Во-вторых, stat-shadows.r
, чтобы определить stat_shadows()
. Код не работает как есть. Но если я выполню его контент, он выдаст желаемую статистику. Для ясности я удалил большинство вычислений в stat_shadows()
, таких как квартили, чтобы сосредоточиться на самом важном. Есть очевидная ошибка в макете?
geom-shadows.r
#' documentation ought to be here
geom_shadows <- function(
mapping = NULL,
data = NULL,
stat = "shadows",
position = "identity",
...,
anchor = list(x = 0, y = 0),
shadows = list("x", "y"),
type = NULL,
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE) {
layer(
data = data,
mapping = mapping,
stat = stat,
geom = GeomShadows,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
anchor = anchor,
shadows = shadows,
type = type,
na.rm = na.rm,
...
)
)
}
GeomShadows <- ggproto("GeomShadows", Geom,
# set up the data, e.g. remove missing data
setup_data = function(data, params) {
data
},
# set up the parameters, e.g. supply warnings for incorrect input
setup_params = function(data, params) {
params
},
draw_group = function(data, panel_params, coord, anchor, shadows, type) {
# draw_group uses stats returned by compute_group
# set common aesthetics
geom_aes <- list(
alpha = data$alpha,
colour = data$color,
size = data$size,
linetype = data$linetype,
fill = alpha(data$fill, data$alpha),
group = data$group
)
# merge aesthetics with data calculated in setup_data
geom_stats <- new_data_frame(c(list(
x = c(data$x.xmin, data$y.xmin),
xend = c(data$x.xmax, data$y.xmax),
y = c(data$x.ymin, data$y.ymin),
yend = c(data$x.ymax, data$y.ymax),
alpha = c(data$alpha, data$alpha)
), geom_aes
), n = 2)
# turn the stats data into a GeomPath
geom_grob <- GeomSegment$draw_panel(unique(geom_stats),
panel_params, coord)
# pass the GeomPath to grobTree
ggname("geom_shadows", grobTree(geom_grob))
},
# set legend box styles
draw_key = draw_key_path,
# set default aesthetics
default_aes = aes(
colour = "blue",
fill = "red",
size = 1,
linetype = 1,
alpha = 1
)
)
stat-shadows.r
#' documentation ought to be here
stat_shadows <-
function(mapping = NULL,
data = NULL,
geom = "shadows",
position = "identity",
...,
# do I need to add the geom_shadows arguments here?
anchor = list(x = 0, y = 0),
shadows = list("x", "y"),
type = NULL,
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE) {
layer(
stat = StatShadows,
data = data,
mapping = mapping,
geom = geom,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
# geom_shadows argument repeated here?
anchor = anchor,
shadows = shadows,
type = type,
na.rm = na.rm,
...
)
)
}
StatShadows <-
ggproto("StatShadows", Stat,
# do I need to repeat required_aes?
required_aes = c("x", "y"),
# set up the data, e.g. remove missing data
setup_data = function(data, params) {
data
},
# set up parameters, e.g. unpack from list
setup_params = function(data, params) {
params
},
# calculate shadows: returns data_frame with colnames: xmin, xmax, ymin, ymax
compute_group = function(data, scales, anchor = list(x = 0, y = 0), shadows = list("x", "y"), type = NULL, na.rm = TRUE) {
.compute_shadows(data = data, anchor = anchor, shadows = shadows, type = type)
}
)
# Calculate the shadows for each type / shadows / anchor
.compute_shadows <- function(data, anchor, shadows, type) {
# Deleted all type-checking, etc. for MWE
# Only 'type = c(double, double)' accepted, e.g. type = c(0, 1)
qs <- type
# compute shadows along the x-axis
if (any(shadows == "x")) {
shadows.x <- c(
xmin = as.numeric(stats::quantile(data[, "x"], qs[[1]])),
xmax = as.numeric(stats::quantile(data[, "x"], qs[[2]])),
ymin = anchor[["y"]],
ymax = anchor[["y"]])
}
# compute shadows along the y-axis
if (any(shadows == "y")) {
shadows.y <- c(
xmin = anchor[["x"]],
xmax = anchor[["x"]],
ymin = as.numeric(stats::quantile(data[, "y"], qs[[1]])),
ymax = as.numeric(stats::quantile(data[, "y"], qs[[2]])))
}
# store shadows in one data_frame
stats <- new_data_frame(c(x = shadows.x, y = shadows.y))
# return the statistics
stats
}
.
draw_group
при объединении эстетики с данными. Код в основном основан наgeom_boxplot
иstat_boxplot
, особенно наwhiskers
. - person PatrickT   schedule 30.12.2018ggplot2::
и скопировать такие функции, какnew_data_frame
, либо (что я делаю) клонировать пакетggplot2
и скомпилировать его с двумя указанными выше файлами, добавленными и правильно указанными вNAMESPACE
иDESCRIPTION
- person PatrickT   schedule 30.12.2018