Так что думал об этом некоторое время. В основном, когда вы создаете новый примитив, вы обычно пишете комбинацию:
- функция слоя
- stat-ggproto,
- geom-ggproto
Только функция слоя должна быть видна пользователю. Вам нужно написать stat-ggproto только в том случае, если вам нужен какой-то новый способ преобразования ваших данных для создания вашего примитива. И вам нужно написать geom-ggproto только в том случае, если вам нужно создать новую графику на основе сетки.
В этом случае, когда мы в основном компостируем уже существующие функции слоя, нам не нужно писать новые ggprotos. Достаточно написать новую функцию слоя. Эта функция слоя создаст три слоя, которые вы уже используете, и сопоставит параметры так, как вы задумали. В таком случае:
- Layer1 — использует
geom_errorbar
и stat_boxplot
— чтобы получить наши полосы ошибок
- Layer2 — использует
geom_boxplot
и stat_boxplot
— для создания коробчатых диаграмм.
- Layer3 — пользователи
geom_label
и stat_summary
— для создания текстовых меток со средним значением в центре полей.
Конечно, вы можете написать новый stat-ggproto и новый geom-ggproto, которые делают все эти вещи одновременно. Или, может быть, вы компостируете stat_summary
и stat_boxplot
в один, а также три geom-protos, и делаете это одним слоем. Но в этом мало смысла, если у нас нет проблем с эффективностью.
В любом случае, вот код:
geom_myboxplot <- function(formula = NULL, data = NULL,
stat = "boxplot", position = "dodge",coef=1.5,
font = "sans", fsize = 18, width=0.6,
fun.data = NULL, fun.y = NULL, fun.ymax = NULL,
fun.ymin = NULL, fun.args = list(),
outlier.colour = NULL, outlier.color = NULL,
outlier.shape = 19, outlier.size = 1.5,outlier.stroke = 0.5,
notch = FALSE, notchwidth = 0.5,varwidth = FALSE,
na.rm = FALSE, show.legend = NA,
inherit.aes = TRUE,...) {
vars <- all.vars(formula)
response <- vars[1]
factor <- vars[2]
mymap <- aes_string(x=factor,y=response)
fun_med <- function(x) {
return(data.frame(y = median(x), label = round(median(x), 3)))
}
position <- position_dodge(width)
l1 <- layer(data = data, mapping = mymap, stat = StatBoxplot,
geom = "errorbar", position = position, show.legend = show.legend,
inherit.aes = inherit.aes, params = list(na.rm = na.rm,
coef = coef, width = width, ...))
l2 <- layer(data = data, mapping = mymap, stat = stat, geom = GeomBoxplot,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(outlier.colour = outlier.colour, outlier.shape = outlier.shape,
outlier.size = outlier.size, outlier.stroke = outlier.stroke,
notch = notch, notchwidth = notchwidth, varwidth = varwidth,
na.rm = na.rm, ...))
l3 <- layer(data = data, mapping = mymap, stat = StatSummary,
geom = "label", position = position, show.legend = show.legend,
inherit.aes = inherit.aes, params = list(fun.data = fun_med,
fun.y = fun.y, fun.ymax = fun.ymax, fun.ymin = fun.ymin,
fun.args = fun.args, na.rm=na.rm,family=font,size=fsize/3,vjust=-0.1,...))
return(list(l1,l2,l3))
}
что позволяет вам создавать свои индивидуальные диаграммы, которые теперь выглядят так:
ggplot(mpg) +
geom_myboxplot( hwy ~ class, font = "sans",fsize = 18)+
theme_grey(base_family = "sans",base_size = 18 )
И выглядят они так:
Примечание: на самом деле нам не нужно было использовать функцию layer
, вместо них мы могли бы использовать исходные вызовы stat_boxplot
, geom_boxplot
и stat_summary
. Но нам все равно пришлось бы заполнять все параметры, если бы мы хотели иметь возможность управлять ими из нашей пользовательской диаграммы, поэтому я думаю, что так было понятнее — по крайней мере, с точки зрения структуры, а не функциональности. . А может и нет, это дело вкуса...
Также у меня нет этого шрифта, который выглядит намного лучше. Но мне не хотелось его отслеживать и устанавливать.
18.02.2016