2016-01-29 2 views
-1

Во многих вариантах, подобные вопросы уже задавали много раз ... , но я не найти четкий совет о:Написание «as.data.frame» для пользовательских S3 объекты

«экспорт методы S3 как функции»

Я написал пользовательский класс S3 с roxygen2, называют его 'my_item'. Это функция-конструктор:

my_item <- function(n) structure(list(n=n),class='my_item') 

Что мне нужно, это способ определить функцию с "list of my_items => data.frame" произнесения:

#' @method as.data.frame my_item 
#' @export 

as.data.frame.my_item <- function(x) ... 

Как только я называю это с my_item таким образом, что это хорошо :

as.data.frame(my_item('a')) 

Но применяя тот же вызов к списку объектов не может работать, потому что class(list) пуст:

as.data.frame(list(my_item('a'),my_item('b'))) 

Это не может работать также потому, что функция/метод не экспортируется

as.data.frame.my_item(list(my_item('a'),my_item('b'))) 

Это не работает с явной квалификацией пространства имен:

my_pkg::as.data.frame.my_item(...) 

Error: 'as.data.frame.my_item' is not an exported object from 'namespace:my_pkg' 

В пакете зоопарка , это возможно для plot общей функции.

См plot.zoo, метод S3, экспортируются как функции:

В зоопарке :: NAMESPACE

export(
    ... 
    "plot.zoo" 
    ... 
) 
S3method("plot", "zoo") 
S3method("as.data.frame", "zoo") 

Полученный пакет является обзорное:

library(zoo) 

methods('as.data.frame') 

[1] as.data.frame.aovproj*  as.data.frame.array   as.data.frame.AsIs   
[4] as.data.frame.character  as.data.frame.chron*   as.data.frame.complex   
[7] as.data.frame.data.frame  as.data.frame.data.table*  as.data.frame.Date   
[10] as.data.frame.dates*   as.data.frame.default   as.data.frame.difftime  
[13] as.data.frame.factor   as.data.frame.ftable*   as.data.frame.integer   
[16] as.data.frame.ITime*   as.data.frame.list   as.data.frame.logical   
[19] as.data.frame.logLik*   as.data.frame.matrix   as.data.frame.model.matrix 
[22] as.data.frame.noquote   as.data.frame.numeric   as.data.frame.numeric_version 
[25] as.data.frame.ordered   as.data.frame.POSIXct   as.data.frame.POSIXlt   
[28] as.data.frame.raw    as.data.frame.shingle*  as.data.frame.table   
[31] as.data.frame.times*   as.data.frame.ts    as.data.frame.vector   
[34] as.data.frame.yearmon*  as.data.frame.yearqtr*  as.data.frame.zoo*   
see '?methods' for accessing help and source code 

methods('plot') 

[1] plot.acf*   plot.data.frame* plot.decomposed.ts* plot.default  plot.dendrogram* 
[6] plot.density*  plot.ecdf   plot.factor*  plot.formula*  plot.function  
[11] plot.hclust*  plot.histogram*  plot.HoltWinters* plot.isoreg*  plot.lm*   
[16] plot.medpolish*  plot.mlm*   plot.ppr*   plot.prcomp*  plot.princomp*  
[21] plot.profile.nls* plot.raster*  plot.shingle*  plot.spec*   plot.stepfun  
[26] plot.stl*   plot.table*   plot.times*   plot.trellis*  plot.ts    
[31] plot.tskernel*  plot.TukeyHSD*  plot.zoo   
see '?methods' for accessing help and source code 

Это показывает, что plot.zoo экспортируется, as.data.frame.zoo* нет т экспортируется


Так что, вероятно, вопрос неправ.

Лучше один будет:

«Как реализовать произнесения-протокол ('как -...') при использовании 'списков-из-списков на основе-S3-объекты'?

+3

Вы посмотрели на это после публикации? пожалуйста, отформатируйте свой код – rawr

+0

Я закрыл, когда я разместил;) – hute37

+0

Возможно, что это немного особый случай, потому что сама функция (т.е. 'as.data.frame') имеет период в ней - противоположность случаю где один экспортирует функцию с периодом, который Roxygen смешивает с методом S3. Если вы сделаете это для функции без периода (например, определите метод «plot» или «summary»), это сработает? –

ответ

0

Я другой подход:

  • добавление 'my_item'+'_list' класса в общий список с помощью функции as.my_item_list()
  • образующей as.data.frame.my_item_list метода, работающего на моих "пользовательских" списков
  • ссылаются на преобразование DF с дженериками: as.data.frame(as.my_item_list(some_list))

В следующем примере, я замещенный my_item имени класса с более коротким ob


ОПРЕДЕЛЕНИЕМ

# ---(the 'ob' S3 constructor)--------------------------------------------- 

ob <- function(a,b) structure(list(a=a,b=b), class='ob') 
is.ob <- function(x) inherits(x,'ob') 

#---(the 'ob_list' cast for lists)----------------------------------------- 

as.ob_list <- function(x, ...) UseMethod('as.ob_list') 
as.ob_list.list <- function(x, ...) { 
    stopifnot(all(sapply(x,is.ob))) 
    class(x) <- append(class(x),'ob_list',after=0) 
    x 
} 

#---(as.data.frame.* methods)---------------------------------------------- 

as.data.frame.ob <- function(x, ...) data.frame(t(as.matrix(unlist(x)))) 
as.data.frame.ob_list <- function(x, ...) do.call('rbind', lapply(x,as.data.frame)) 

ТЕСТ

o1 <- ob(1,10) 
o2 <- ob(2,20) 
o3 <- ob(3,30) 

ol <- list(o1,o2,o3) 

df <- as.data.frame(as.ob_list(ol)) 

print(df) 

    a b 
1 1 10 
2 2 20 
3 3 30 

Он выглядит хорошо!

+0

Хорошо, но Slooow. В CRAN есть лучшие способы, такие как ['dplyr coertion'] (https://github.com/hadley/dplyr/blob/master/vignettes/data_frames.Rmd), ... – hute37

+0

Выше реализации, взятой из http: // stackoverflow .com/вопросы/4227223/г-лист к данным кадра – hute37

Смежные вопросы