+ - 0:00:00
Notes for current slide
Notes for next slide

Classes and Methods in R

https://github.com/rdpeng/CourseraLectures/blob/master/classes-methods.Rnw

Modified after Roger Peng’s lecture

https://youtu.be/93N0HdoZW9g

10-11-2021

1 / 32

Classes and Methods

  • A system for doing object oriented programming

  • R is both interactive and has a system for object orientation.

    • Other languages which support OOP (C++, Java, Lisp, Python, Perl) generally speaking are not interactive languages
  • Object oriented programming is a bit different in R than it is in most languages - even if you are familiar with the idea, you may want to pay attention to the details
2 / 32

Two styles of classes and methods

S3 classes/methods

  • Essentially a list with a class attribute on it
  • Informal, you can assign any class to any list, which is nonsense
  • Sometimes called old-style classes/methods

S4 classes/methods

  • More formal and rigorous
  • Included with S-PLUS 6 and R 1.4.0 (December 2001)
  • Also called new-style classes/methods
3 / 32

Two worlds living side by side

  • For now (and the forseeable future), S3 classes/methods and S4 classes/methods are separate systems (but they can be mixed to some degree).

  • Each system can be used fairly independently of the other.

  • Developers of new projects (you!) are encouraged to use the S4 style classes/methods.

4 / 32

Object Oriented Programming in R

  • A class is a description of an thing. A class can be defined using setClass() in the methods package.

  • An object is an instance of a class. Objects can be created using new().

  • A method is a function that only operates on a certain class of objects.

  • A generic function is an R function which dispatches methods. A generic function typically encapsulates a "generic" concept (e.g. plot, mean, predict, ...)

  • A method is the implementation of a generic function for an object of a particular class.
5 / 32

Things to look up

  • The help files for the methods package are extensive - do read them as they are the primary documentation

  • You may want to start with ?Classes and ?Methods

  • Check out ?setClass, ?setMethod, and ?setGeneric

  • Use class? prefix for help on specific classes, e.g., class?GRanges

6 / 32

Classes

All objects in R have a class which can be determined by the class function

class(1)
## [1] "numeric"
class(TRUE)
## [1] "logical"
class(rnorm(100))
## [1] "numeric"
class(NA)
## [1] "logical"
class("foo")
## [1] "character"
7 / 32

Classes (cont'd)

Data classes go beyond the atomic classes

x <- rnorm(100)
y <- x + rnorm(100)
fit <- lm(y ~ x) ## linear regression model
class(fit)
## [1] "lm"
names(fit)
## [1] "coefficients" "residuals" "effects" "rank"
## [5] "fitted.values" "assign" "qr" "df.residual"
## [9] "xlevels" "call" "terms" "model"
isS4(fit)
## [1] FALSE
8 / 32

Classes (cont'd)

getClass("lm")
## Virtual Class "lm" [package "methods"]
##
## Slots:
##
## Name: .S3Class
## Class: character
##
## Extends: "oldClass"
##
## Known Subclasses:
## Class "mlm", directly
## Class "aov", directly
## Class "glm", directly
## Class "maov", by class "mlm", distance 2
## Class "glm.null", by class "glm", distance 2
9 / 32

Generics/Methods in R

  • S4 and S3 style generic functions look different but conceptually, they are the same (they play the same role).

  • When you program you can write new methods for an existing generic OR create your own generics and associated methods.

  • Of course, if a data type does not exist in R that matches your needs, you can always define a new class along with generics/methods that go with it

10 / 32

An S3 generic function (in the base package)

The mean function is generic

mean
## function (x, ...)
## UseMethod("mean")
## <bytecode: 0x7f90107b2a08>
## <environment: namespace:base>

So is the print function

print
## function (x, ...)
## UseMethod("print")
## <bytecode: 0x7f8ff61573b0>
## <environment: namespace:base>
11 / 32

S3 methods

methods("mean")
## [1] mean.Date mean.default mean.difftime mean.POSIXct mean.POSIXlt
## [6] mean.quosure*
## see '?methods' for accessing help and source code
12 / 32

An S4 generic function (from the methods package)

The S4 equivalent of print is show

show
## standardGeneric for "show" defined from package "methods"
##
## function (object)
## standardGeneric("show")
## <bytecode: 0x7f8fe6a9a138>
## <environment: 0x7f9006d7cee8>
## Methods may be defined for arguments: object
## Use showMethods(show) for currently available ones.
## (This generic function excludes non-simple inheritance; see ?setIs)

The show function is usually not called directly (much like print) because objects are auto-printed

13 / 32

S4 methods

Think of S4 methods as simple functions that perform certain task depending on class

mimicMethod <- function(x) {
if (is(x, "matrix"))
method1(x)
if (is(x, "data.frame"))
method2(x)
if (is(x, "IRanges"))
method3(x)
}
14 / 32

Generic/method mechanism

The first argument of a generic function is an object of a particular class (there may be other arguments)

  • The generic function checks the class of the object.

  • A search is done to see if there is an appropriate method for that class.

  • If there exists a method for that class, then that method is called on the object and we're done.

  • If a method for that class does not exist, a search is done to see if there is a default method for the generic. If a default exists, then the default method is called.

  • If a default method doesn't exist, then an error is thrown.

15 / 32

Examining Code for Methods

Examining the code for an S3 or S4 method requires a call to a special function

  • You cannot just print the code for a method like other functions because the code for the method is usually hidden.

  • If you want to see the code for an S3 method, you can use the function getS3method.

    • The call is getS3method(<generic>, <class>)
  • For S4 methods you can use the function getMethod

    • The call is getMethod(<generic>, <signature>) (more details later)
16 / 32

Examining Code for Methods

> showMethods("mean")
Function: mean (package base)
x="ANY"
x="AtomicList"
x="CompressedIntegerList"
x="CompressedLogicalList"
x="CompressedNumericList"
x="CompressedRleList"
x="Rle"
x="Views"
17 / 32

S3 Class/Method: Example 1

What's happening here?

set.seed(2)
x <- rnorm(100)
mean(x)
## [1] -0.03069816
  • The class of x is numeric
  • But there is no mean method for numeric objects!
  • So we call the default function for mean.
18 / 32

S3 Class/Method: Example 1

getS3method("mean", "default")
## function (x, trim = 0, na.rm = FALSE, ...)
## {
## if (!is.numeric(x) && !is.complex(x) && !is.logical(x)) {
## warning("argument is not numeric or logical: returning NA")
## return(NA_real_)
## }
## if (na.rm)
## x <- x[!is.na(x)]
## if (!is.numeric(trim) || length(trim) != 1L)
## stop("'trim' must be numeric of length one")
## n <- length(x)
## if (trim > 0 && n) {
## if (is.complex(x))
## stop("trimmed means are not defined for complex data")
## if (anyNA(x))
## return(NA_real_)
## if (trim >= 0.5)
## return(stats::median(x, na.rm = FALSE))
## lo <- floor(n * trim) + 1
## hi <- n + 1 - lo
## x <- sort.int(x, partial = unique(c(lo, hi)))[lo:hi]
## }
## .Internal(mean(x))
## }
## <bytecode: 0x7f8fe606f2a8>
## <environment: namespace:base>
19 / 32

S3 Class/Method: Example 2

What happens here?

set.seed(3)
df <- data.frame(x = rnorm(100), y = 1:100)
sapply(df, mean)
## x y
## 0.01103557 50.50000000
  • The class of df is data.frame; in a data frame each column can be an object of a different class
  • We sapply over the columns and call the mean function
  • In each column, mean checks the class of the object and dispatches the appropriate method.
  • Here we have a numeric column and an integer column; in both cases mean calls the default method
20 / 32

Calling Methods

  • Some methods are visible to the user (i.e. mean.default)

  • You should never call methods directly

  • Use the generic function and let the method be dispatched automatically

21 / 32

S3 Class/Method: Example 3

The plot function is generic and its behavior depends on the object.

set.seed(10)
x <- rnorm(100)
plot(x)

22 / 32

S3 Class/Method: Example 3

For time series objects, plot connects the dots

set.seed(10)
x <- rnorm(100)
y <- x + rnorm(100)
fit <- lm(y ~ x) ## linear regression model
par(mfrow = c(1, 4))
plot(fit)

23 / 32

Write your own methods!

If you write new methods for new classes, you'll probably end up writing methods for the following generics:

  • print/show
  • summary
  • plot

There are two ways that you can extend the R system via classes/methods

  • Write a method for a new class but for an existing generic function (i.e. like print)
  • Write new generic functions and new methods for those generics
24 / 32

S4 Classes

Why would you want to create a new class?

  • To represent new types of data (e.g. gene expression, space-time, hierarchical, sparse matrices)

  • New concepts/ideas that haven't been thought of yet (e.g. a fitted point process model, mixed-effects model, a sparse matrix)

  • To abstract/hide implementation details from the user

25 / 32

S4 Class/Method: Creating a New Class

A new class can be defined using the setClass function

  • At a minimum you need to specify the name of the class

  • You can also specify data elements that are called slots

  • You can then define methods for the class with the setMethod function

  • Information about a class definition can be obtained with the showClass function

26 / 32

S4 Class/Method: Polygon Class

Creating new classes/methods is usually not something done at the console; you likely want to save the code in a separate file

setClass("polygon",
representation(x = "numeric",
y = "numeric"))

The slots for this class are x and y. The slots for an S4 object can be accessed with the @ operator.

You should never have to access slots directly. You should get/set data out of the class slot using the "accessor" functions (getters and setters).

27 / 32

S4 Class/Method: Polygon Class

  • A plot method can be created with the setMethod function.
    • Specify a generic function(plot), and a class signature.
setMethod("plot", "polygon",
function(x, y, ...) {
plot(x@x, x@y, type = "n", ...)
xp <- c(x@x, x@x[1])
yp <- c(x@y, x@y[1])
lines(xp, yp)
})

Note that the slots of the polygon (the x- and y-coordinates) are accessed with the @ operator.

If things go well, you will not get any messages or errors and nothing useful will be returned by either setClass or setMethod.

28 / 32

S4 Class/Method: Polygon Class

After calling setMethod the new plot method will be added to the list of methods for plot.

showMethods("plot")
## Function: plot (package base)
## x="ANY"
## x="polygon"

Note that the signature for class polygon is listed. The method for ANY is the default method and it is what is called when now other signature matches

29 / 32

S4 Class/Method: Polygon class

p <- new("polygon", x = c(1, 2, 3, 4), y = c(1, 2, 3, 1))
plot(p)

30 / 32

Class inheritance

  • Class inheritance is used when you define a new class which “is almost like this other class but with a little twist”.

  • For example ExpressionSet inherits from eSet, and when you look at the class definition you cannot easily see a difference. The difference is that ExpressionSet is meant to contain expression data and has the exprs() accessor.

31 / 32

References

32 / 32

Classes and Methods

  • A system for doing object oriented programming

  • R is both interactive and has a system for object orientation.

    • Other languages which support OOP (C++, Java, Lisp, Python, Perl) generally speaking are not interactive languages
  • Object oriented programming is a bit different in R than it is in most languages - even if you are familiar with the idea, you may want to pay attention to the details
2 / 32
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow