проверка имени аргумента в scale_continuous_fill ()

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
1
задан Richard Erickson 17 January 2019 в 17:16
поделиться

1 ответ

Короткий ответ

Предполагая, что ваш объект 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:

ggplot_build берет объект заговора и выполняет все шаги, необходимые для создания объекта, который может быть визуализирован. Эта функция выводит две части: список фреймов данных (по одному для каждого слоя) и объект панели, который содержит всю информацию об ограничениях оси, разрывах и т. Д.

Из ?ggplot_gtable:

Эта функция создает все графы, необходимые для отображения графика, и сохраняет их в специальной структуре данных, называемой 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)
    }

Давайте проверим, так ли это на самом деле:

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)
[1179 ] 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 мы внезапно переходим от того, что слишком мало мест ищите название легенды, чтобы иметь слишком много. Вот они в порядке приоритета:

  1. Если определено g.build$plot$guides[["fill"]] и значение g.build$plot$guides[["fill"]]$title не равно waiver(): g.build$plot$guides[["fill"]]$title;
  2. Остальное, если Значение g.build$plot$scales$scales[[1]]$guide$title не равно waiver(): g.build$plot$scales$scales[[1]]$guide$title;
  3. Остальное, если значение g.build$plot$scales$scales[[1]]$name не равно waiver(): g.build$plot$scales$scales[[1]]$name;
  4. Остальное: [ +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
)

multiple titles for the same scale

Резюме : Теперь, когда мы вылезли обратно из кроличьей норы , мы знаем, что в зависимости от того, где вы определили заголовок для своей легенды, вы можете найти его в соответствующем месте в вашем объекте 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"
0
ответ дан Z.Lin 17 January 2019 в 17:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: