R objects and functions Sren Hjsgaard Department of Mathematical - - PowerPoint PPT Presentation

r objects and functions
SMART_READER_LITE
LIVE PREVIEW

R objects and functions Sren Hjsgaard Department of Mathematical - - PowerPoint PPT Presentation

R objects and functions Sren Hjsgaard Department of Mathematical Sciences Aalborg University, Denmark October 15, 2012 Printed: October 15, 2012 File: objects-slides.tex 2 Contents 1 Attributes 3 1.1 class attributes . . . . . . . . .


slide-1
SLIDE 1

R objects and functions

Søren Højsgaard Department of Mathematical Sciences Aalborg University, Denmark October 15, 2012

Printed: October 15, 2012 File: objects-slides.tex

slide-2
SLIDE 2

2

Contents

1 Attributes 3 1.1 class attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 More about classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2 The S3 object system 7 2.1 Example: Single exponential smoothing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.2 Generic functions and methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3 More about generic functions and methods . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.4 Multiple inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.5 Example: Double exponential smoothing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.6 EXERCISES: Exponential smoothing and the S3 system . . . . . . . . . . . . . . . . . . . . . 23

slide-3
SLIDE 3

3

1 Attributes

An attribute of an R object is another R object attached by a name to the object:

R> x <- 123 R> attr(x,"foo") <- "something" R> attr(x,"bar") <- c(1,10) R> x [1] 123 attr(,"foo") [1] "something" attr(,"bar") [1] 1 10 R> attr(x,"foo") [1] "something" R> attributes(x) $foo [1] "something" $bar [1] 1 10

slide-4
SLIDE 4

4

1.1 class attributes

A class is an example of an attribute:

R> (today <- Sys.Date()) [1] "2012-10-15" R> dput(today) structure(15628, class = "Date") R> ff <- factor(c(1,2,1,2)) R> dput(ff) structure(c(1L, 2L, 1L, 2L), .Label = c("1", "2"), class = "factor")

The class can be retrieved with

R> class(today) [1] "Date" R> class(ff) [1] "factor"

slide-5
SLIDE 5

5

1.2 More about classes

However not all objects have classes (in terms of a class attribute) – but class() still returns“the class”of an object. It all seems to be not entirely consistent, but there is a long history behind things

R> MM <- matrix(1:4, nrow=2) R> dput(MM) structure(1:4, .Dim = c(2L, 2L)) R> class(MM) [1] "matrix" R> AA <- array(1:8, dim=c(2,2,2)) R> dput(AA) structure(1:8, .Dim = c(2L, 2L, 2L)) R> class(AA) [1] "array"

slide-6
SLIDE 6

6 R> VV <- 1:8 R> dim(VV) <- 8 R> dput(VV) structure(1:8, .Dim = 8L) R> class(VV) [1] "array"

  • Neither of these objects have a class attribute.
  • It is the dim attribute that determines the class.
  • In fact, a matrix is also an array:

R> is(MM, "array") [1] TRUE

slide-7
SLIDE 7

7

2 The S3 object system

There are two approaches to“object” –oriented programming in R: S3–classes and S4–classes.

  • The S3–system has been around for a very long time and it is easy to use (to

program and to document).

  • The S4–system is much newer and somewhat more involved to use.

We only look at the S3–system here:

  • Create generic functions (example: summary())
  • Create a summary() method for objects of class "foo"; i.e. a function called

summary.foo().

  • When calling summary() on an object of class "foo" the call will dispatch to

the summary() method for "foo" objects; i.e. to summary.foo().

slide-8
SLIDE 8

8

2.1 Example: Single exponential smoothing

The Nile data contains measurements of the annual flow of the river Nile at Ashwan 1871–1970. There seems to be a drow around year 1900. Why?

R> data(Nile) R> plot(Nile)

Time Nile 1880 1900 1920 1940 1960 600 800 1200

slide-9
SLIDE 9

9

We make a single exponential smoothing of data: St = αyt + (1 − α)St−1, S1 = y1 where 0 < α < 1. Given data up to time t the natural forecast h time steps ahead is ˆ yt+h|t = St so the one–step–ahead forecast error is et = yt − ˆ yt|t−1 = yt − St−1. An alternative form is: St = St−1 + α(yt − St−1) = St + αet

slide-10
SLIDE 10

10

A simple function that does the steps above is:

R> ses <- function(yvar, alpha=.1){ n.obs <- length(yvar) sss <- rep.int(NA, n.obs) sss[1] <- yvar[1] for (ii in 2:n.obs){ sss[ii] <- alpha * yvar[ii] + (1-alpha)*sss[ii-1] } res <- list(x=1:n.obs, y=sss, y.obs=yvar) class(res) <- c('sesObj','list') res } R> sss <- ses(as.numeric(Nile)) R> str(sss) List of 3 $ x : int [1:100] 1 2 3 4 5 6 7 8 9 10 ... $ y : num [1:100] 1120 1124 1108 1118 1122 ... $ y.obs: num [1:100] 1120 1160 963 1210 1160 1160 813 1230 1370 1140 ...

  • attr(*, "class")= chr [1:2] "sesObj" "list"

Notice: The result is a list but with an added class attributes.

slide-11
SLIDE 11

11

The result (a list) can be plotted with

R> plot(as.numeric(Nile)) R> lines(y~x, data=sss)

  • 20

40 60 80 100 600 800 1200 Index as.numeric(Nile)

But we can also take a more object oriented approach.

slide-12
SLIDE 12

12

2.2 Generic functions and methods

The plot–function is a generic function. The action of plot depends on what we try to plot (a model object, a matrix, at dataframe). We create a plot–method for sesObj–objects:

R> plot.sesObj <- function(x,...){ plot(x$x, x$y.obs,...) lines(x$x, x$y, col='red',...) } R> plot(sss,pch=16)

slide-13
SLIDE 13

13

  • 20

40 60 80 100 600 800 1200 x$x x$y.obs

slide-14
SLIDE 14

14

Other methods that might be of relevance

R> residuals.sesObj <- function(object, ...) {

  • bject$y.obs - object$y

} R> fitted.sesObj <- function(object, ...) {

  • bject$y

}

Notice one detail: We can coerce the result to a dataframe even though we have not defined an as.data.frame()–method for sesObj–objects:

R> aa <- as.data.frame(sss) R> head(aa) x y y.obs 1 1 1120.000 1120 2 2 1124.000 1160 3 3 1107.900 963 4 4 1118.110 1210 5 5 1122.299 1160 6 6 1126.069 1160

slide-15
SLIDE 15

15 R> class(sss) [1] "sesObj" "list"

This works because R first checks if there is a as.data.frame()–method for sesObj–objects. If so, this method is applied; if not then R checks if there ´ ıs a as.data.frame()–method for a lists. Such a method exists and is this method is applied.

slide-16
SLIDE 16

16

2.3 More about generic functions and methods

R> ## Generic function: R> goodFun <- function(x){ UseMethod('goodFun') } R> ## Default method: R> goodFun.default <- function(x){ cat("Don't know what to do here\n") } R> zzz <- 123 R> goodFun(zzz) Don't know what to do here R> class(zzz) <- 'foo' R> goodFun(zzz) This is a 'foo' object: 123

The generic function goodFun() will look for an appropriate method to apply to the input. In absence of such an appropriate method the generic function will resort to a default method.

slide-17
SLIDE 17

17

We create a goodFun method for foo objects

R> ## Method for foo objects R> goodFun.foo <- function(x){ cat(sprintf("This is a 'foo' object: %s\n", toString(x))) } R> goodFun(zzz) This is a 'foo' object: 123

slide-18
SLIDE 18

18

2.4 Multiple inheritance

We can work with multiple inheritance: An object can have classes bar and foo, and in this setting the goodFun method for bar is called first:

R> ## Method for bar objects R> goodFun.bar <- function(x){ cat(sprintf("This is a 'bar' object: %s\n", toString(x))) } R> class(zzz) <- c('bar', 'foo') R> goodFun(zzz) This is a 'bar' object: 123

slide-19
SLIDE 19

19

We can call the method for the next class in the hierarchy using NextMethod:

R> ## Method for bar objects R> goodFun.bar <- function(x){ cat(sprintf("This is a 'bar' object: %s\n", toString(x))) NextMethod(x) } R> class(zzz) <- c('bar', 'foo') R> goodFun(zzz) This is a 'bar' object: 123 This is a 'foo' object: 123

slide-20
SLIDE 20

20

2.5 Example: Double exponential smoothing

Single expo- nential smoothing does not work well when there is a trend in data, i.e. if yt ≈ a+bt

R> y <- log(as.numeric(JohnsonJohnson)) R> se <- ses(y,.1) R> plot(se,xlab='')

  • 20

40 60 80 1 2 x$y.obs

slide-21
SLIDE 21

21

Single exponential smoothing will be biased in the sense that yt − St = bβ α for t → ∞

  • r yt ≈ St + b β

α where β = 1 − α.

If we smooth St (i.e. smooth data twice) we get S[2]

t

= (a − 2bβ α) + bt for t → ∞ Hence S[2]

t

− St → b β

α. From these considerations therefore have

b = {St − S[2]

t }α

β (1) yt = St − bβ/α = St + (St − S[2]

t ) = 2Stt − S[2] t

(2)

slide-22
SLIDE 22

22

Hence natural estimates of levels and slopes become ˆ yt = St + {St − S[2]

t } = 2St − S[2] t

(3) ˆ bt = {St − S[2]

t }α

β (4) Similarly, the forecasts become ˆ yt+h|t = ˆ yt + ˆ bth (5)

slide-23
SLIDE 23

23

2.6 EXERCISES: Exponential smoothing and the S3 system

  • 1. Create a function called des() that will do double exponential smoothing.

This function can be (and should be) implemented by calling the ses() function from the lecture twice.

  • 2. Create print(), plot(), residual() and fitted() methods that will work
  • n the results from single and from doubly smoothed data.
  • 3. Create a generic forecast() function and forecast() methods for single

and doubly exponentially smoothed data. The methods should for a given time t and a given h > 0 produce the forecasts for time t, t + 1, . . . t + h based on the data available up to and including time t.

  • 4. Using the forecast() methods, investigate whether better predictions are
  • btained from doubly smoothed than from single smoothed data.