Making S3 Objects with Constructors

S3 classes do not really need to be defined prior to object creation and there is no real need for a constructor function either. An S3 object is created once the class attribute is set.

obj <- list(age = 24, name = "Eze", sex = "male")
is.object(obj)   # FALSE
attr(obj, which = "class") <- "teacher"
is.object(obj)   # TRUE
class(obj)       # "teacher"

So, you see? No constructor needed.

An S3 constructor would look something like this:

  • Named after the class itself
  • Have some validation/error-checking
  • In the body, create a list
  • Could take members of a list as arguments
  • Also in the body, assign the class name to the list
  • Return the object upon termination

I learnt about these from this very useful blog.

Now let me get down to the real subject of this post…

A dataframe in R is essentially a list of equal-length vectors and one can create different objects of the same class to represent each record within a dataset.

dataframe

This is where a constructor will prove very useful. How about writing a script that will generate a collection of objects of a particular class from a given dataframe?

This is the approach I employed:

  1. Make a constructor function
  2. Apply the constructor to each row of a dataframe
  3. Create a collection of objects returned by the constructor i.e. a list

I wrote a script to do just that:

# Create a data frame
df <- data.frame(Name = c("Mike Adebayo", "Joan Deer", "Marcus Aurelius"),
                 Age = c(47, 52, 78),
                 Sex = factor(c("Male", "Female", "Male")),
                 stringsAsFactors = FALSE)
rownames(df) <- LETTERS[1:nrow(df)]
str(df)
attr(df, "row.names")

# S3 constructor
RecordS3 <- function(x, y, z) {
    structure(list(Name = x, Age = y, Sex = z), class = "RecordS3")
}

# Create objects from the data
objects <- list(nrow(df))
for (i in seq_along(rownames(df))) {    # are 'apply' functions better here?
    arg <- list(ncol(df))
    for (j in seq_along(colnames(df))) {
        arg[[j]] <- df[i, j]
    }
    objects[[i]] <- RecordS3(arg[[1]], arg[[2]], arg[[3]])
}
str(objects)

This could easily be extended to a dataframe with scores, even hundreds of records. Whether it’s any good for big data is something I’m yet to explore for now. Also, this business would be most useful if it can be done generically. I’m yet to know how to do that, but will do a blog once I do.

Comments

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s