8

I'm creating a custom function in R that takes as input a few different variables and creates a data.frame, a plot, and some summary stats, all stored in a list. I'd like to only print out the summary stats when calling the function, but have the plot and data.frame available when called explicitly.

I think what I want is similar to how lm() operates but I'm not sure how it is acheiving that.

When I print the object returned by lm I only get a printout of $call and $coefficients:

lm(mtcars$mpg ~ mtcars$cyl)

Call:
lm(formula = mtcars$mpg ~ mtcars$cyl)

Coefficients:
(Intercept)   mtcars$cyl  
     37.885       -2.876  

But clearly behind the scenes there is much more available in the function call to lm.

lm(mtcars$mpg[1:3] ~ mtcars$cyl[1:3])$residuals
            1             2             3 
-1.280530e-15  1.280530e-15  8.365277e-31 

> unclass(lm(mtcars$mpg[1:3] ~ mtcars$cyl[1:3])

Call:
lm(formula = mtcars$mpg[1:3] ~ mtcars$cyl[1:3])

Coefficients:
    (Intercept)  mtcars$cyl[1:3]  
           26.4             -0.9  


> unclass(lm(mtcars$mpg[1:3] ~ mtcars$cyl[1:3]))
$coefficients
    (Intercept) mtcars$cyl[1:3] 
           26.4            -0.9 

$residuals
            1             2             3 
-1.280530e-15  1.280530e-15  8.365277e-31 

$effects
    (Intercept) mtcars$cyl[1:3]                 
  -3.741230e+01    1.469694e+00    1.810943e-15 

....

$call
lm(formula = mtcars$mpg[1:3] ~ mtcars$cyl[1:3])

$model
  mtcars$mpg[1:3] mtcars$cyl[1:3]
1            21.0               6
2            21.0               6
3            22.8               4

I looked at the code for lm but it's not very clear to me what is going on.

Vincent Bonhomme
  • 7,235
  • 2
  • 27
  • 38
pedram
  • 2,931
  • 3
  • 27
  • 43
  • 4
    When you call `lm()`, the output sent to the terminal is produced by a call to `print.lm()`. (It gets dispatched to by the S3 generic function `print` which looks for and finds a method for an object of class `lm`.) To see the code used by `print.lm()`, type `getAnywhere("print.lm")`. [See also here](http://stackoverflow.com/questions/10938427/example-needed-change-the-default-print-method-of-an-object/10938565#10938565) for one example of how to develop your own custom print method. – Josh O'Brien May 25 '16 at 16:50
  • 2
    You should look at the code for `lm` and also for `stats:::print.lm` and then read `?Methods`, I think (though it's over my head). – Frank May 25 '16 at 16:50
  • You have to make your list into an S3 object and create a `print` method for it. The best explained example of this is in this article I think. https://cran.r-project.org/doc/contrib/Leisch-CreatingPackages.pdf. That article shows how to create a package, the example being a simplified object similar to `lm` – Mike Wise May 25 '16 at 16:54
  • To do this, you need to learn something about S3 classes and methods. This answer will get you started: http://stackoverflow.com/q/6583265/602276 – Andrie May 25 '16 at 17:08
  • 1
    Also, if you want to explore the structure of the object created by lm (or any other) you can use `str`. – Vincent Bonhomme May 25 '16 at 17:59

1 Answers1

10

The result of a call to lm is an object with the class attribute set to lm. Objects of this class have their own print method (which you can call explicitly if you want using print.lm). You can do something similar yourself simply by setting the class attribute of the object returned by your function and then writing your own print method. Here's an example:

my.func <- function(x, y, z){
    library(ggplot2)
    df <- data.frame(x, y, z)
    p <- ggplot(df, aes(x, y)) + geom_point()
    ds <- sapply(df, summary)

    op <- list(data = df, plot = p, summary = ds)
    class(op) <- 'my_list'
    op
}

print.my_list <- function(m){
    print(m$summary)
}

a <- my.func(1:5, 5:1, rnorm(5))
a
print.default(a)

Because the list a has the class attribute set to my_list, once you have created a print method for it, this method is used whenever you print a list with that class. You can see the entire object by explicitly calling print.default. There is a very good explanation of classes in R here: http://adv-r.had.co.nz/OO-essentials.html.

David_B
  • 926
  • 5
  • 7