R Преобразование нескольких функций в один объект с помощью объектно-ориентированного программирования (S3 и S4)

Я пытаюсь понять, как превратить функции в объектно-ориентированное программирование на R. Так, например, как данные и 2 функции, приведенные ниже, можно превратить в один объект с помощью S3 (а затем S4)? (Может быть, некоторые другие простые данные и функции лучше послужат примерами?)

data <- c(1, 2, 3)

# Function 1
adding_1 <- function(x){
  x <- x+1
}

# Function 2
subtracting_1 <- function(x){
  x <- x-1
}

И как бы функции ниже выполнялись с использованием ООП.

data1 <- adding_1(data)
data1
data2 <- subtracting_1(data)
data2

1 ответ

Решение

В R объектно-ориентированное программирование реализовано несколькими разными способами.
Объектно-ориентированный тип S3 используется чаще всего, потому что он очень прост и все же хорошо справляется с тем, чтобы, казалось бы, одни и те же функции ведут себя по-разному с разными типами объектов. Хорошая ссылка - Advanced R от Hadley Wickham.

В объектах R есть attributes. Одним из таких атрибутов является особыйclassатрибут. Вы можете увидеть это с помощью

x <- 1:3
y <- c(1, 2, 3)
class(x)    # "integer"
class(y)    # "numeric"

Система S3 - это система с перегрузкой функций. Определена специальная функция, общая. Затем определяются другие функции, методы, для обработки объектов в зависимости от их классов. Метод, который необходимо определить, является методом по умолчанию.

Здесь я использую ваш пример, чтобы определить сначала общий, а затем метод по умолчанию.

# Function 1
adding_1 <- function(x, ...) UseMethod("adding_1")
adding_1.default <- function(x, ...){
  x <- x + 1
  x
}

Теперь методы для объектов класса "list" а также "data.frame".

adding_1.list <- function(x, ...){
  num <- sapply(x, is.numeric)
  x[num] <- lapply(x[num], adding_1)
  x
}
adding_1.data.frame <- function(x, ...){
  num <- sapply(x, is.numeric)
  x[num] <- lapply(x[num], adding_1)
  x
}

И то же самое для subtracting_1.

# Function 2
subtracting_1 <- function(x, ...) UseMethod("subtracting_1")
subtracting_1.default <- function(x){
  x <- x - 1
  x
}
subtracting_1.list <- function(x, ...){
  num <- sapply(x, is.numeric)
  x[num] <- lapply(x[num], subtracting_1)
  x
}
subtracting_1.data.frame <- function(x, ...){
  num <- sapply(x, is.numeric)
  x[num] <- lapply(x[num], subtracting_1)
  x
}

Тестовые примеры.

При звонке с x в качестве аргумента (или y выше) это метод по умолчанию, который вызывается, поскольку нет adding_1.integer ни adding_1.numeric.

И то же самое касается mat.

Но при вызове с фреймом данных требуется специальная обработка, чтобы функция не пыталась добавить 1 в символьные строки или другие типы нечисловых векторов-столбцов, которые могут быть во фрейме данных.

mat <- matrix(1:6, 3)
df1 <- data.frame(x = letters[1:5], y = rnorm(5), z = 101:105)

adding_1(x)
adding_1(mat)
adding_1(df1)

subtracting_1(x)
subtracting_1(mat)
subtracting_1(df1)
Другие вопросы по тегам