Dealing with S3 methods in R with a simple example
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
By Gabriel Vasconcelos
S3 objects
R
has three object systems: S3, S4 and RC. S3 is by far the easiest to work with and it can make you codes much understandable and organized, especially if you are working on a package. The idea is very simple. First we must define a class to some object in R
and then we define methods (functions) for this class based on generic functions that you may create or use the ones available.
Step 1: Defining the object’s class
The function below runs a linear regression and estimate the relevant statistics. Note that in the function I generate several objects and in the end I put them all in a list. Finally, I define the attribute class for my list.
regression=function(x,y){ x=cbind(1,x) beta=solve(t(x)%*%x)%*%t(x)%*%y residuals=y-x%*%beta fitted.values=x%*%beta sigmae=(t(residuals)%*%residuals)/(nrow(x)-ncol(x)) stde=sqrt(diag(c(sigmae)*solve(t(x)%*%x))) tstat=beta/stde pvalue=2*pt(-abs(tstat),df=nrow(x)-ncol(x)) res=list(coefficients=beta,residuals=residuals,fitted.values=fitted.values, stde=stde,tstat=tstat,pvalue=pvalue,y=y) class(res)="regression" # Class definition return(res) }
Now let’s use the function in some data and see what happens. If I ask R
for the class of the resulting object it gives me the defined class “regression”. Additionally, there are some cool stuff you can do that has nothing to do with the class but with the way I defined the list res
. If you type coef(res)
, residuals(res)
or fitted(res)
you will get coefficients, residuals and fitted values. This will happen every time you name the objects in the list in the way I just did.
set.seed(123) x=matrix(rnorm(10*100),100,10) colnames(x)=1:10 y=x%*%rep(1,ncol(x))+rnorm(100) test=regression(x,y) class(test) # check the class ## [1] "regression"
Step 2: Defining methods for “regression”“ class
If you look at the documentation in some functions you will read “S3 method for class ‘XXX’”. Try ?summary.lm
for example. summary
is a generic function that will define which method to call. The .lm
tells R
that the method to be called in this case is the one defined for the class lm.
To define our own method we just need to create a function using generic.class
. However, the defined function must have all arguments in the generic function in the same order. For example, summary
takes the argument “object” and the argument “…”. Your function must have the same two arguments in the same order plus the extra arguments you need. There are some exceptions. The function plot
takes “x”, “y” and “…” but you may write your plot method without the argument “y”.
In the code below I defined a plot and a summary method for the class “regression”.
plot.regression=function(x,...){ plot(x$y,main="Fitted x Observed",type="l") lines(fitted(x),col=2) } summary.regression=function(object,digits=4,...){ tab=cbind(coef(object),object$stde,object$tstat,object$pvalue) colnames(tab)=c("coef","stde","t","p") rownames(tab)=rownames(coef(object)) rownames(tab)[1]="Cons." print(tab,digits=digits) }
Now we can call your functions using only their generic name and R
will automatically identify the right method to use.
summary(test,3) ## coef stde t p ## Cons. 0.137 0.109 1.25 2.14e-01 ## 1 1.065 0.120 8.87 6.94e-14 ## 2 0.996 0.112 8.88 6.73e-14 ## 3 0.853 0.112 7.61 2.67e-11 ## 4 1.138 0.109 10.47 3.37e-17 ## 5 1.070 0.113 9.45 4.37e-15 ## 6 0.963 0.118 8.17 1.92e-12 ## 7 1.093 0.104 10.55 2.35e-17 ## 8 1.110 0.110 10.12 1.82e-16 ## 9 0.951 0.103 9.27 1.03e-14 ## 10 1.137 0.106 10.69 1.20e-17 plot(test)
Final Remarks
As you can see, S3 objects are very easy to deal with. You can also define multiple classes to an object. If you are writing a package you have to be careful to export the functions in the right way. Fortunately, the RStudio tool for packages combined with the roxygen2 package does most of the job for you. You can identify generic functions reading the description in their documentation.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.