PersonX = function(){};
Помещает ссылку на анонимную функцию на
PersonX
.PersonX
указывает на функцию.PersonY = new function(){};
Помещает ссылку на вновь созданный экземпляр анонимной функции-конструктора в
PersonY
.PersonY
указывает на объект.Что касается прототипа, у него есть
PersonY
. Однако, поскольку не было никаких свойств и методов, связанных с конструктором до или после экземпляра, у него есть пустой прототип *.Фактически вы можете проверить прототип
PersonY
, выполнивconsole.log(PersonY)
. Вы увидите, что у него есть свойство прототипа (я вижу его как__proto__
в Chrome), который является «пустым». Но он имеет 2 скрытых свойства,constructor
, который является конструкторской функцией, создавшей объект, и другой__proto__
, который ведет вас к следующей «цепочке», которая будет объектомObject
.* Не совсем пустая, так как прототип - это цепочка. Этот уровень прототипа может быть пустым, но следующий более высокий прототип может иметь или в этом случае иметь свойства и методы.
Object prototype -> Constructor prototype -> Your Instance will have: - toString() - blank - toString() - hasOwnProperty() - hasOwnProperty() - and more... - and more... - ...but nothing from Constructor
Предполагая, что ваш объект ggplot назван p
, и вы указали аргумент name
в своей шкале, он будет найден в p$scales$scales[[i]]$name
(где i
соответствует порядок шкалы).
Ниже приводится длинный рассказ о том, как я его нашел. Не обязательно отвечать на вопрос, но он может помочь вам в следующий раз, когда вы захотите найти что-то в ggplot.
Начальная точка : часто полезно преобразовать объект ggplot в объект grob, поскольку последний позволяет нам делать все виды вещей, которые мы не можем легко взломать в ggplot (например, построить geom на краю области графика без обрезки закрасьте разные полосы фасетов разными цветами, вручную добавьте ширину фасета для каждого фасета, добавьте график на другую карту в качестве пользовательской аннотации и т. д.).
В пакете ggplot2 есть функция ggplotGrob
, которая выполняет преобразование. Это означает, что если мы рассмотрим шаги на этом пути, мы сможем найти шаг, который найдет заголовок шкалы в объекте ggplot, чтобы преобразовать его в некоторый вид textGrob.
Это, в свою очередь, означает, что мы собираемся взять следующую единственную строку кода & amp; переходите вниз по последовательным слоям, пока мы не выясним, что происходит под капотом:
ggplotGrob(my_plot)
Слой 1 : ggplotGrob
сам по себе является просто оболочкой для двух функций, ggplot_build
и [1117 ]. [тысяча сто семьдесят-оден]
> ggplotGrob
function (x)
{
ggplot_gtable(ggplot_build(x))
}
Из ?ggplot_build
:
blockquote>
ggplot_build
берет объект заговора и выполняет все шаги, необходимые для создания объекта, который может быть визуализирован. Эта функция выводит две части: список фреймов данных (по одному для каждого слоя) и объект панели, который содержит всю информацию об ограничениях оси, разрывах и т. Д.Из
?ggplot_gtable
:Эта функция создает все графы, необходимые для отображения графика, и сохраняет их в специальной структуре данных, называемой
blockquote>gtable()
. Этот объект поддается программным манипуляциям, если вы хотите (например) сделать блок легенды шириной 2 см или объединить несколько сюжетов в один экран, сохраняя пропорции по всем сюжетам.Уровень 2 : и
ggplot_build
, иggplot_gtable
просто возвращают универсальныйUseMethod("<function name>"
при входе в консоль, и соответствующие функции не экспортируются из пакета ggplot2 , Тем не менее, вы можете найти их на GitHub (ссылка ) или получить к ним доступ в любом случае с помощью тройного двоеточия:::
.> ggplot2:::ggplot_build.ggplot function (plot) { plot <- plot_clone(plot) # ... omitted for space layout <- create_layout(plot$facet, plot$coordinates) data <- layout$setup(layer_data, plot$data, plot$plot_env) # ... omitted for space structure(list(data = data, layout = layout, plot = plot), class = "ggplot_built") } > ggplot2:::ggplot_gtable.ggplot_built function (data) { plot <- data$plot layout <- data$layout data <- data$data theme <- plot_theme(plot) # ... omitted for space position <- theme$legend.position %||% "right" # ... omitted for space legend_box <- if (position != "none") { build_guides(plot$scales, plot$layers, plot$mapping, position, theme, plot$guides, plot$labels) } # ... omitted for space }
Мы видим, что в
ggplot2:::ggplot_gtable.ggplot_built
есть фрагмент кода, который создает поле легенды:legend_box <- if (position != "none") { build_guides(plot$scales, plot$layers, plot$mapping, position, theme, plot$guides, plot$labels) }
Давайте проверим, так ли это на самом деле:
[1179 ]g.build <- ggplot_build(my_plot) legend.box <- ggplot2:::build_guides( g.build$plot$scales, g.build$plot$layers, g.build$plot$mapping, "right", ggplot2:::plot_theme(g.build$plot), g.build$plot$guides, g.build$plot$labels) grid::grid.draw(legend.box)
И это действительно так. Давайте увеличим масштаб, чтобы увидеть, что делает
ggplot2:::build_guides
.Уровень 3 : в
ggplot2:::build_guides
мы видим, что после некоторых строк кода, которые обрабатывают положение блока легенды & amp; выравнивание, определения руководства (gdefs
) генерируются функцией с именемguides_train
:> ggplot2:::build_guides function (scales, layers, default_mapping, position, theme, guides, labels) { # ... omitted for space gdefs <- guides_train(scales = scales, theme = theme, guides = guides, labels = labels) # .. omitted for space }
Как и раньше, мы можем подключить соответствующее значение для каждого аргумента & amp; проверьте, что говорится в этих определениях руководства:
gdefs <- ggplot2:::guides_train( scales = g.build$plot$scales, theme = ggplot2:::plot_theme(g.build$plot), guides = g.build$plot$guides, labels = g.build$plot$labels ) > gdefs [[1]] $title expression("Legend name"^2) $title.position NULL #... omitted for space
Да, есть ожидаемое имя шкалы:
expression("Legend name"^2)
.ggplot2:::guides_train
(или какая-то функция внутри него) вытащила его изg.build$plot[1133]lt;something>
/ggplot2:::plot_theme(g.build$plot)
, но нам нужно копать глубже, чтобы увидеть, какие & amp; как.Уровень 4 : В
ggplot2:::guides_train
мы находим строку кода, которая берет заголовок легенды из одного из нескольких возможных мест:> guides_train function (scales, theme, guides, labels) { gdefs <- list() for (scale in scales$scales) { for (output in scale$aesthetics) { guide <- guides[[output]] %||% scale$guide # ... omitted for space guide$title <- scale$make_title(guide$title %|W|% scale$name %|W|% labels[[output]]) # ... omitted for space } } gdefs }
(
ggplot2:::%||%
и [ 1137] являются неэкспортированными функциями из пакета, они принимают два значения, возвращая первое значение, если оно определено / не отменено, и второе в противном случае.)Annnnnnnnnnd мы внезапно переходим от того, что слишком мало мест ищите название легенды, чтобы иметь слишком много. Вот они в порядке приоритета:
- Если определено
g.build$plot$guides[["fill"]]
и значениеg.build$plot$guides[["fill"]]$title
не равноwaiver()
:g.build$plot$guides[["fill"]]$title
;- Остальное, если Значение
g.build$plot$scales$scales[[1]]$guide$title
не равноwaiver()
:g.build$plot$scales$scales[[1]]$guide$title
;- Остальное, если значение
g.build$plot$scales$scales[[1]]$name
не равноwaiver()
:g.build$plot$scales$scales[[1]]$name
;- Остальное: [ +1148]. [тысяча сто шестьдесят четыре]
Мы также знаем из изучения кода
ggplot2:::ggplot_build.ggplot
, чтоg.build$plot
по существу совпадает с первоначально введеннымmy_plot
, поэтому вы можете заменить каждый экземплярg.build$plot
в списке выше наmy_plot
].Дополнительное примечание : это тот же список приоритетов, который вступает в игру, если ваш объект ggplot имеет какой-то кризис идентичности и содержит несколько заголовков легенд, определенных для одного масштаба. Иллюстрация ниже:
base.plot <- ggplot(df, aes(x = x, y = y, group = group, fill = z )) + geom_polygon() cowplot::plot_grid( # plot 1: title defined in guides() overrides titles defined in `scale_...` base.plot + ggtitle("1") + scale_fill_continuous( name = "scale", low = "skyblue", high = "orange", guide = guide_colorbar(title = "guide in scale")) + guides(fill = guide_colorbar(title = "guide")), # plot 2: title defined in scale_...'s guide overrides scale_...'s name base.plot + ggtitle("2") + scale_fill_continuous( name = "scale", low = "skyblue", high = "orange", guide = guide_colorbar(title = "guide in scale")), # plot 3: title defined in `scale_...'s name base.plot + ggtitle("3") + scale_fill_continuous( name = "scale", low = "skyblue", high = "orange"), # plot 4: with no title defined anywhere, defaults to variable name base.plot + ggtitle("4") + scale_fill_continuous( low = "skyblue", high = "orange"), nrow = 2 )
Резюме : Теперь, когда мы вылезли обратно из кроличьей норы , мы знаем, что в зависимости от того, где вы определили заголовок для своей легенды, вы можете найти его в соответствующем месте в вашем объекте ggplot. Однако то, будет ли этот заголовок действительно отображаться на графике, зависит от того, определили ли вы также другой заголовок с более высоким приоритетом ...
sample.plot <- ggplot(df, aes(x = x, y = y, group = group, fill = z )) + geom_polygon() + scale_fill_continuous( name = "title3", guide = guide_colorbar(title = "title2")) + guides(fill = guide_colorbar(title = "title1")) > sample.plot$guides[["fill"]]$title [1] "title1" > sample.plot$scales$scales[[1]]$guide$title [1] "title2" > sample.plot$scales$scales[[1]]$name [1] "title3" > sample.plot$labels[["fill"]] [1] "z"