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

Я пытаюсь понять, как превратить функции в объектно-ориентированное программирование на R. Так, например, как можно преобразовать данные и две функции ниже в один объект с помощью 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
}

И как будут выполняться функции ниже, используя OOP.

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

1 Ответ

3 голосов
/ 08 февраля 2020

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

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

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

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

Здесь я использую ваш пример для определения сначала универсального c, а затем метода по умолчанию.

# 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 к символьным строкам или другим типам нечисловых c векторов столбцов, которые могут быть в кадре данных.

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)
...