A brief look at the class mechanism in R

by Karl-Kuno Kunze

This post shows some of the peculiarities of R. The brute force way to assign classes to less structured objecs

  • is not the only way
  • may not be appropriate.

Mechanism 1

Usually, being member of a certain class is expressed by an attribute called ‘class’. So the following three expressions are somewhat equivalent:

myD1 <- as.Date("1970-01-02")

myD2 <- 1
class(myD2) <- "Date"

myD3 <- 1
attr(myD3, "class") <- "Date"

myD1; myD2; myD3
## [1] "1970-01-02"
## [1] "1970-01-02"
## [1] "1970-01-02"

You may check with the attributes() and identical() statements, that they are really identical:

attributes(myD1); attributes(myD2)
## $class
## [1] "Date"
## $class
## [1] "Date"
identical(myD1, myD2)
## [1] TRUE

Taking the class away, either through a casting function, through unclass(), or through setting the attribute to NULL, is shown here:

myD1 <- as.numeric(myD1)

myD2 <- unclass(myD2)

attr(myD3, "class") <- NULL

myD1; myD2; myD3
## [1] 1
## [1] 1
## [1] 1

All three elements are plain vectors now with one element.

Mechanism 2

However, look at this:

myM <- matrix(c(1:4), nrow= 2)
class(myM)
## [1] "matrix"
myM <- unclass(myM)
class(myM)
## [1] "matrix"
myM
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4

What is going on here? Although we took away the class, it still remembers its class ‘matrix’.

Let’s have a closer look at the attributes:

attributes(myM)
## $dim
## [1] 2 2

In fact, there is no attribute ‘class’, but rather an attribute called ‘dim’. Let’s use this for some manipulations. First we rip off the attribute:

attr(myM, "dim") <- NULL
class(myM)
## [1] "integer"
myM
## [1] 1 2 3 4

Now we attach it again

attr(myM, "dim") <- c(2,2)
class(myM)
## [1] "matrix"
myM
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4

That is, the attribute ‘class’ is not the only attribute to eventually set a class. Even more, let us now set an attribute class to the value ‘Date’:

attr(myM, "class") <- "Date"
myM
## [1] "1970-01-02" "1970-01-03" "1970-01-04" "1970-01-05"
attributes(myM)
## $dim
## [1] 2 2
## 
## $class
## [1] "Date"

So, if there is an attribute ‘class’ it overrides any secondary class affiliation