12.3 Orientación a objetos

R está orientado a objetos. Los objetos son estructuras que combinan datos y funciones que operan sobre ellos y son muy útiles en un entorno, como R, pensado para el análisis estadístico de datos. Por ejemplo, el resultado de una regresión lineal es un objeto (de clase lm):

mi.modelo <- lm(dist ~ speed, data = cars)
class(mi.modelo)
## [1] "lm"

El objeto mi.modelo contiene información relevante acerca del modelo lineal: coeficientes, resíduos, p-valores, etc. Se puede consultar esta información haciendo, por ejemplo,

str(mi.modelo)

Pero, además, existen funciones como summary, plot o predict que saben cómo operar sobre un objeto de la clase lm como el anterior proporcionando los resultados esperados.

12.3.1 Polimorfismo

El polimorfismo es una característica del lenguaje que se logra en R gracias a la orientación a objetos. Permite que una única función, p.e., summary, opere de manera distinta dependiendo de su argumento. La siguiente discusión pone de manifiesto la utilidad del polimorfismo y cómo la orientación a objetos de R es fundamental para conseguirla.

Nótese que el objeto mi.modelo construido más arriba es también una lista:

is.list(mi.modelo)
## [1] TRUE

En realidad, nuestro modelo es una lista a la que se ha añadido un atributo class que lo identifica como un modelo lineal, i.e., lm. Por contra, iris es una tabla, es decir, otro tipo especial de lista, una con atributo class data.frame. En el fondo, ambos son listas; sin embargo, la función summary proporciona información distinta sobre ellos:

summary(iris)
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.350   Median :1.300  
##  Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199  
##  3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
##  Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :50  
##  versicolor:50  
##  virginica :50  
##                 
##                 
## 
summary(mi.modelo)
## 
## Call:
## lm(formula = dist ~ speed, data = cars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -29.069  -9.525  -2.272   9.215  43.201 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -17.5791     6.7584  -2.601   0.0123 *  
## speed         3.9324     0.4155   9.464 1.49e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 15.38 on 48 degrees of freedom
## Multiple R-squared:  0.6511, Adjusted R-squared:  0.6438 
## F-statistic: 89.57 on 1 and 48 DF,  p-value: 1.49e-12

Es precisamente a través del atributo class que R implementa el polimorfismo, i.e, que una misma función opere de manera distinta sobre objetos distintos. Lo mismo ocurre con otras funciones genéricas como plot, print o predict.

En realidad, detrás de summary existen muchas funciones que son versiones específicas (o métodos) suyas. Las disponibles para summary, son

methods(summary)
##  [1] summary,ANY-method             summary.aov                   
##  [3] summary.aovlist*               summary.arma*                 
##  [5] summary.aspell*                summary.check_packages_in_dir*
##  [7] summary.connection             summary.data.frame            
##  [9] summary.Date                   summary.default               
## [11] summary.ecdf*                  summary.factor                
## [13] summary.garch*                 summary.ggplot*               
## [15] summary.glm                    summary,GridTopology-method   
## [17] summary.infl*                  summary.lm                    
## [19] summary.loess*                 summary.loglm*                
## [21] summary.manova                 summary.matrix                
## [23] summary.mlm*                   summary.negbin*               
## [25] summary.nls*                   summary.packageStatus*        
## [27] summary.PDF_Dictionary*        summary.PDF_Stream*           
## [29] summary.polr*                  summary.POSIXct               
## [31] summary.POSIXlt                summary.ppr*                  
## [33] summary.prcomp*                summary.princomp*             
## [35] summary.proc_time              summary,quantmod-method       
## [37] summary.rlm*                   summary.shingle*              
## [39] summary,Spatial-method         summary.srcfile               
## [41] summary.srcref                 summary.stepfun               
## [43] summary.stl*                   summary.table                 
## [45] summary.trellis*               summary.tukeysmooth*          
## [47] summary.XMLInternalDocument*   summary.yearmon*              
## [49] summary.yearqtr*               summary.zoo*                  
## see '?methods' for accessing help and source code

Cuando summary se aplica sobre un objeto de la clase lm, la versión de summary que se le aplica es summary.lm; cuando se aplica sobre iris, se utiza summary.data.frame, etc. Obviamente, es responsabilidad de los autores de lm definir las funciones summary.lm, print.lm, plot.lm, etc.

12.3.1.1 Para saber más

Para saber más sobre clases y orientación a objetos en R, puedes leer https://www.datanalytics.com/2011/08/04/desarrollo-de-paquetes-con-r-iv-funciones-genericas/. Ahí se discute cómo asignar atributos de clase a objetos y cómo crear métodos y, si procede, nuevas funciones genéricas.

En R existen varios mecanismos para dotarlo de la orientación a objetos. En esta sección hemos explorado superficialmente la más simple, la conocida como S3 (que corresponde con la tercera especificación del lenguaje). Existen otros mecanismos más formales de clases (p.e., las de las clases S4), que utilizan algunos paquetes de R. Por ejemplo, gran parte de los que se usan en geoestadística.