Sebastien Renaut
Sebastien Renaut

Reputation: 71

which plot() is being used?

In R, you often see plot() being used with very different kinds of data with very different default outcomes. plot() recognizes which object it is been given and uses the proper function according to this object.

In the example below plot() actually refers to ape::plot.phylo().

library(ape)
tree.owls <- 
  read.tree(text = 
              "(((Strix_aluco:4.2,Asio_otus:4.2):3.1, Athene_noctua:7.3):6.3,Tyto_alba:13.5);")
plot(tree.owls)

Question is: how do you know that in this case plot() refers to plot.phylo()? More generally, ss there a way to find out that would apply to any object being plotted (vector, df, list, S3, S4, etc.)?

Upvotes: 3

Views: 717

Answers (2)

SEAnalyst
SEAnalyst

Reputation: 1211

plot() is a generic function. The ape package has a method for the plot function, which is plot.phylo. When a package is loaded into an R session, any methods for each generic function are cached in your environment.

If you try methods(plot), you will see all the various plot() methods available in your environment. Here are two nifty lines for seeing information about each plot method in your environment.

m <- methods("plot")     
print(attr(m, "info"))  

So how does plot() know to use plot.phylo and not plot.default or one of the many other available plot methods? The package authors use their method on objects with a particular class attribute. In this case, the class attribute is "phylo". We can see the class attribute with str() or dplyr::glimpse():

> str(tree.owls)
List of 4
 $ edge       : int [1:6, 1:2] 5 6 7 7 6 5 6 7 1 2 ...
 $ edge.length: num [1:6] 6.3 3.1 4.2 4.2 7.3 13.5
 $ Nnode      : int 3
 $ tip.label  : chr [1:4] "Strix_aluco" "Asio_otus" "Athene_noctua" "Tyto_alba"
 - attr(*, "class")= chr "phylo"
 - attr(*, "order")= chr "cladewise"

If a given object does not have the class attribute required for the method, it will try other methods of the function, finally trying the default method, which is in this case is plot.default

Upvotes: 2

Justin Landis
Justin Landis

Reputation: 2071

As other's have mentioned, this has to do with S3 method dispatch. You can check what the class of an object is with the class function. In this case it returns phylo.

A lot of generic functions have many methods. You can check all the methods by using methods("plot").

The source code for the plot function is

function (x, y, ...) 
UseMethod("plot")

and the UseMethod function will search for the available methods on the generic function given. If it can find the method, in this case plot.phylo then it will execute that method, otherwise it uses the next method or the default method.

So to reiterate, what method plot uses entirely depends on the class of the object, not so much if the object is a dataframe, vector, list, etc. Classes are convenient in guaranteeing a function will behave in an expected way.

To really make a point, you can define your own plot method too. Take this for example:

plot.foo <- function(x){
      str(x)
      plot(iris)
}

obj1 <- 1:3
class(obj1) <- "foo"
obj2 <- list(x = 2, y = 1:100)
class(obj2) <- "foo"

#No matter the object we pass, so long as the class if "foo",
# our custom plot method is called

plot(obj1)
#Class 'foo'  int [1:3] 1 2 3
plot(obj2)
#List of 2
 #$ x: num 2
 #$ y: int [1:100] 1 2 3 4 5 6 7 8 9 10 ...
 # - attr(*, "class")= chr "foo"

Upvotes: 2

Related Questions