Подтвердить что ты не робот

Плохая идея? ggplotting объект класса S3

У многих объектов R есть методы S3, связанные с ними. Например, каждый R-регрессионный учебник содержит примерно следующее:

dat <- data.frame(x=runif(10))
dat$y <- dat$x+runif(10)
my.lm <- lm( y~x, dat )
plot(my.lm)

Отображает регрессионную диагностику.

Аналогично, у меня есть объект S3 для пакета, который состоит из списка, который в основном содержит несколько временных рядов. У меня есть метод plot.myobject для него, который входит в список, вытягивает временные ряды и выстраивает их на одном графике. Я хотел бы переписать это как функцию ggplot2, чтобы она была более красивой и, возможно, более расширяемой.

Поскольку этот пакет предназначен для быстрого и быстрого запуска людей, , я хотел бы, чтобы это был однострочный с одним аргументом, как в plot(myobject), ggplot(myobject), или что бы ни была подходящей версией. Затем, как только они зацепились, они могут узнать больше о ggplot2 и настроить график на их содержание в сердце.

Мой первоначальный соблазн состоял в том, чтобы просто заменить внутренности метода plot.myobject на использование ggplot2. Это, однако, похоже, что это может потерять меня в главных точках стиля.

Это плохая идея, и если да, то почему и какую альтернативу я должен использовать?

4b9b3361

Ответ 1

Согласно предложению Хэдли в комментариях, я представил общий S3 autoplot() в репозиторий ggplot2 Github. Поэтому, если он будет принят и проверен, в будущем для этого использования должен быть autoplot.

Обновление

autoplot теперь доступен в ggplot2.

Ответ 2

В ggplot2 существует существующая идиома, чтобы сделать именно то, что вы предлагаете. Он называется fortify. Он принимает объект и создает версию объекта в форме, с которой может работать ggplot, т.е. Data.frame. В разделе 9.3 в книге Hadley ggplot2 описано, как это сделать, например, с использованием класса объектов S3 lm. Чтобы увидеть это в действии, введите fortify.lm в свою консоль, чтобы получить следующий код:

function (model, data = model$model, ...) 
{
    infl <- influence(model, do.coef = FALSE)
    data$.hat <- infl$hat
    data$.sigma <- infl$sigma
    data$.cooksd <- cooks.distance(model, infl)
    data$.fitted <- predict(model)
    data$.resid <- resid(model)
    data$.stdresid <- rstandard(model, infl)
    data
}
<environment: namespace:ggplot2>

Вот мой собственный пример написания метода fortify для tree, первоначально опубликованного на список рассылки ggplot2

fortify.tree <- function(model, data, ...){
  require(tree)
  # Uses tree:::treeco to extract data frame of plot locations
  xy <- tree:::treeco(model)
  n <- model$frame$n

  # Lines copied from tree:::treepl
  x <- xy$x
  y <- xy$y
  node = as.numeric(row.names(model$frame))
  parent <- match((node%/%2), node)
  sibling <- match(ifelse(node%%2, node - 1L, node + 1L), node)

  linev <- data.frame(x=x, y=y, xend=x, yend=y[parent], n=n)
  lineh <- data.frame(x=x[parent], y=y[parent], xend=x,
      yend=y[parent], n=n)

  rbind(linev[-1,], lineh[-1,])

} 

theme_null <- opts(
    panel.grid.major = theme_blank(),
    panel.grid.minor = theme_blank(),
    axis.text.x = theme_blank(),
    axis.text.y = theme_blank(),
    axis.ticks = theme_blank(),
    axis.title.x = theme_blank(),
    axis.title.y = theme_blank(),
    legend.position = "none"
)

И код сюжета. Обратите внимание, что данные, переданные в ggplot, не являются объектами data.frame, а tree.

library(ggplot2)
library(tree)

data(cpus, package="MASS")
cpus.ltr <- tree(log10(perf) ~ syct+mmin+mmax+cach+chmin+chmax, cpus)

p <- ggplot(data=cpus.ltr) + 
    geom_segment(aes(x=x,y=y,xend=xend,yend=yend,size=n),
      colour="blue", alpha=0.5) + 
    scale_size("n", to=c(0, 3)) + 
    theme_null
print(p) 

enter image description here

Ответ 3

Использование plot.myobject легко запомнить и выполнить. Однако, если вы говорите о myobject, у которого уже есть функции plot.myobject, вы должны беспокоиться о разных версиях в разных пространствах имен. Но если это только для ваших собственных myobject s, вы не потеряете ни одного стиля. Пакет nlme, например, делает это широко, хотя с решетчатыми графами вместо ggplot.

Использование ggplot.myobject является альтернативой; вам не придется беспокоиться о других версиях, если другие люди не начнут делать то же самое. Однако, как вы заметили, это нарушает парадигму использования ggplot.

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

Ответ 4

ggplot и ggplot2 обычно ожидают, что данные придут к ним в форме расплава(). Таким образом, вашим методам может потребоваться расплавление (из пакета plyr), а затем "сопоставить" полученные имена столбцов с аргументами в методах ggplot.