Вызовите setup_data из родительского класса - PullRequest
1 голос
/ 21 марта 2019

Backround

Я читал этот превосходный ответ о том, как разместить самонастраивающийся текст в столбцы: Изменяемый размер текстовых защелок внутри столбцов

После прочтения немного по ggproto и особенно по виньетке Расширение ggplot Мне было интересно, почему автор должен был определить подпрограмму setup_data следующим образом:

GeomFit <- ggproto("GeomFit", GeomRect,
               setup_data = function(data, params) {
                 data$width <- data$width %||%
                   params$width %||% (resolution(data$x, FALSE) * 0.9)
                 transform(data,
                           ymin = pmin(y, 0), ymax = pmax(y, 0),
                           xmin = x - width / 2, xmax = x + width / 2, width = NULL
                 )
               })

Поскольку это, по сути, копия вставки из ggplot2::GeomBar:

GeomBar$setup_data
# <ggproto method>
#   <Wrapper function>
#     function (...) 
# f(...)

#   <Inner function (f)>
#     function (data, params) 
# {
#     data$width <- data$width %||% params$width %||% (resolution(data$x, 
#         FALSE) * 0.9)
#     transform(data, ymin = pmin(y, 0), ymax = pmax(y, 0), xmin = x - 
#         width/2, xmax = x + width/2, width = NULL)
# }

Так что я подумал, что могу заменить это просто:

GeomFit <- ggproto("GeomFit", GeomRect,
                   setup_data = function(self, data, params)
                      ggproto_parent(GeomBar, self)$setup_data(data, params))

Этот подход работает, но у меня есть сомнения, может ли это привести к нежелательному поведению, просто потому что родительский класс GeomFit равен GeomRect, а не GeomBar.

Вопрос

Можно ли (в смысле: нет условий, в которых это может вызвать проблемы) использовать ggproto_parent для вызова функции из класса, который не является родительским классом моего ggproto объекта? Почему ggproto_parent имеет аргумент parent в первую очередь? Разве родитель не должен быть в любом случае определен вторым аргументом ggproto?

1 Ответ

1 голос
/ 27 марта 2019

Я не участвую в разработке пакета ggplot2, но я попробую сделать это, так как это была неделя, и никто больше не публиковал пока ...

Ниже приведены соответствующие определения функций, которые я скопировал с страницы ggplot2 GitHub :

ggproto_parent <- function(parent, self) {
  structure(list(parent = parent, self = self), class = "ggproto_parent")
}

`$.ggproto_parent` <- function(x, name) {
  res <- fetch_ggproto(.subset2(x, "parent"), name)
  if (!is.function(res)) {
    return(res)
  }

  make_proto_method(.subset2(x, "self"), res)
}

Из первой функции мы можем сделать вывод, что ggproto_parent(GeomBar, self) в этом случае вернет список из двух элементов, list(parent = GeomBar, self = self) (где self разрешается до GeomFit). Этот список передается второй функции как x.

Затем вторая функция ищет в x[["parent"]] метод, соответствующий данному имени, в данном случае setup_data (fetch_ggproto), и связывает его с x[["self"]], если рассматриваемая функция включает self параметр (make_proto_method).

Ни одна из функций не проверяет родительский элемент GeomFit (к которому можно обратиться в GeomFit$super()), поэтому я не думаю, что GeomBar вместо GeomRect в ggproto_parent() действительно имеет значение.


Тем не менее, я бы, наверное, использовал что-то вроде этого:

GeomFit <- ggproto("GeomFit", GeomRect,
                   setup_data = .subset2(GeomBar, "setup_data"))

или это:

GeomFit <- ggproto("GeomFit", GeomRect,
                   setup_data = environment(GeomBar$setup_data)$f)

Что делает для более короткого кода.

...