Диспетчеризация методов для классов S3 в R: определение метода для конкретного подкласса нескольких более высоких классов

Я работаю над коллекцией скриптов и использую классы и методы s3, чтобы все было немного чище.

Структура класса состоит из трех уровней.

  • Уровень 1: data.frame
  • Уровень 2: sample_report ИЛИ fix_report
  • Уровень 3: стим_репорт

Я хочу написать функцию, которая ТОЛЬКО принимает фреймы данных классаtim_report, а затем отправляет другой метод в зависимости от того, наследуется ли стим_репорт от sample_report или наследуется от fix_report.

Очевидно, я мог бы сделать что-то вроде

myfunction.stim_report(df)

if ("sample_report" %in% class(df)) {
% do something 
} else if ("fix_report" %in% class(df)) {
% do something 
}

Но это поражает цель диспетчеризации методов.

Обратите внимание, что мне нужно, чтобы все работало, чтобы функция возвращала ошибку, если класс фрейма данных не являетсяtim_report. Так что, полагаю, я мог бы также:

myfunction.fix_report(df)
if ("stim_report" %in% class(df)) {
% do something 
} else {
stop("No method found")
}

myfunction.sample_report(df)
if ("stim_report" %in% class(df)) {
% do something 
} else {
stop("No method found")
}

Но опять же, похоже, что это идет вразрез со всей сутью методов S3.

Есть ли правильный способ сделать это?


person jwdink    schedule 30.08.2014    source источник


Ответы (1)


Как насчет чего-то вроде этого -

Df1 <- data.frame(
  x = 1:5,
  y = rexp(5))
##
Df2 <- data.frame(
  x = 6:10,
  y = rexp(5))
##
Df3 <- data.frame(
  x = 11:15,
  y = rexp(5))
##
class(Df1) <- c("stim_report","sample_report","data.frame")
class(Df2) <- c("stim_report","fix_report", "data.frame")
##
foo <- function(x){
  UseMethod("foo",x)
}
foo.sample_report <- function(x){
  x[sample(1:nrow(x),3),]
}
foo.fix_report <- function(x){
  x[,2] <- cumsum(x[,2])
  x
}
##
> foo(Df1)
  x         y
3 3 0.9400994
5 5 0.3708902
1 1 0.7521028
> foo(Df2)
   x        y
1  6 2.408421
2  7 2.637971
3  8 3.465672
4  9 3.571835
5 10 5.468710
> foo(Df3)
Error in UseMethod("foo", x) : 
  no applicable method for 'foo' applied to an object of class "data.frame"

Где бы вы изменили тела foo.sample_report и foo.fix_report, чтобы они делали то, что вы хотите. Классы объектов были назначены как c("stim_report","sub_class", "data.frame"), а не просто c("stim_report","sub_class"), чтобы они могли наследовать другие универсальные шаблоны S3, например nrow.

person nrussell    schedule 30.08.2014
comment
Спасибо! Работает как шарм. - person jwdink; 30.08.2014