Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell what method is being used by a function call when `methods` fails?

Might as well let the cat out of the bag and say that I have been trying for about a day to figure out what is happening when I call plot for an object of class SpatialPolygons*. My instinct is to look for plot.SpatialPolygonsDataFrame, the approach which works for any number of other examples I've seen & encountered, but this failed.

Quick example:

US States .shp file here.

library(maptools)
us.states<-readShapePoly("cb_2014_us_state_5m.shp")
plot(us.states)

A sample plot. It shows the polygons of all the US states and territories placed on an invisible globe. It's hard to read, but the plot is not the main thing for this question.

A bit dumpy but whatever--the point is that a simple call to plot and somewhere deep down R knew which method to call in order to give us a representation of all the shapes.

After searching around a bit, I tried two of the other approaches suggested by various SO Q&As, first and foremost:

> methods(plot)
 [1] plot.aareg*                         plot.acf*                          
 [3] plot,ANY,ANY-method                 plot.cox.zph*                      
 [5] plot.data.frame*                    plot.decomposed.ts*                
 [7] plot.default                        plot.dendrogram*                   
 [9] plot.density*                       plot.ecdf                          
[11] plot.factor*                        plot.formula*                      
[13] plot.function                       plot.hclust*                       
[15] plot.histogram*                     plot.HoltWinters*                  
[17] plot.isoreg*                        plot.lm*                           
[19] plot.medpolish*                     plot.mlm*                          
[21] plot.ppr*                           plot.prcomp*                       
[23] plot.princomp*                      plot.profile.nls*                  
[25] plot.raster*                        plot.shingle*                      
[27] plot,SpatialGrid,missing-method     plot,SpatialLines,missing-method   
[29] plot,Spatial,missing-method         plot,SpatialPixels,missing-method  
[31] plot,SpatialPoints,missing-method   plot,SpatialPolygons,missing-method
[33] plot.spec*                          plot.spline*                       
[35] plot.stepfun                        plot.stl*                          
[37] plot.survfit*                       plot.table*                        
[39] plot.times*                         plot.trellis*                      
[41] plot.ts                             plot.tskernel*                     
[43] plot.TukeyHSD*                      plot.xyVector*                     
[45] plot.zoo*                              

The answer would appear to be in slots 27-32; however, each is followed by a vexing comma! No mention that this is possible in ?methods and ?plot,SpatialPolygons,missing-method is an error. A quick search for missing-method turns up nothing of use and there's again no mention in ?methods.

OK; moving on. What about getS3method? getMethod? getMethods? getAllMethods??

> getS3method("plot","SpatialPolygonsDataFrame")
Error in getS3method("plot", "SpatialPolygonsDataFrame") : 
  S3 method 'plot.SpatialPolygonsDataFrame' not found

> getMethod("plot","SpatialPolygonsDataFrame")
Error in getMethod("plot", "SpatialPolygonsDataFrame") : 
  no method found for function 'plot' and signature SpatialPolygonsDataFrame

The latter two are deprecated & also return nothing.

So apparently these functions are just a stand-in for my first instincts.

So now what? How can I tell which method is being called by plot when it is passed a SpatialPolygonsDataFrame? Is there any general approach to this problem that supersedes the approach I used above?

Edit:

Sort of by accident I stumbled upon this (=?`Spatial-Polygons-class` ) which says:

The plot method for spatial polygons takes the following arguments:

but it still doesn't say what that method is, exactly.

like image 210
MichaelChirico Avatar asked Sep 04 '15 00:09

MichaelChirico


People also ask

What is it called when a method calls another method?

Recursion is a method that call itself. In this case it is a recursion.

How is calling a method different from calling a function?

A function has another property: all calls to a function with the same parameters, should return the same result. A method, on the other hand, is a function that is related to an object in an object-oriented language.

What's the difference between method and function?

A function is a set of instructions or procedures to perform a specific task, and a method is a set of instructions that are associated with an object.

What is the difference between method and function in Java?

Difference Between Function and Method:The javascript method is an object property that has a function value. A function can pass the data that is operated and may return the data. The method operates the data contained in a Class. Data passed to a function is explicit.


2 Answers

Partial answer: the method is sp:::plot.SpatialPolygons. I have no idea why those commas are showing up in the results of methods(plot); plot,SpatialPolygons,missing-method makes no sense to me (and I see it too).

I found the answer by causing an error. I don't have your shape file, so I took the example from help("SpatialPolygonsDataFrame-class"), which I got to from ?SpatialPolygons". The example is below:

Sr1 = Polygon(cbind(c(2,4,4,1,2),c(2,3,5,4,2)))
Sr2 = Polygon(cbind(c(5,4,2,5),c(2,3,2,2)))
Sr3 = Polygon(cbind(c(4,4,5,10,4),c(5,3,2,5,5)))
Sr4 = Polygon(cbind(c(5,6,6,5,5),c(4,4,3,3,4)), hole = TRUE)
Srs1 = Polygons(list(Sr1), "s1")
Srs2 = Polygons(list(Sr2), "s2")
Srs3 = Polygons(list(Sr3, Sr4), "s3/4")
SpP = SpatialPolygons(list(Srs1,Srs2,Srs3), 1:3)
plot(SpP, col = 1:3, pbg="white")

I then changed the plot call to give an error:

plot(SpP, col = kasjdhfkjasdfhkas, pbg = "white")
# Error in plot.SpatialPolygons(x, ...) : object 'kasjdhfkjasdfhkas' not found

(should work unless you have kasjdhfkjasdfhkas defined in your workspace as a vector). Sure enough,

sp:::plot.SpatialPolygons

showed the code for the method.

like image 184
Gregor Thomas Avatar answered Sep 28 '22 16:09

Gregor Thomas


To answer a couple of questions raised by Gregor. The methods function did not formerly display results for S4-methods, but now it does. Doing a search in the NEWS document I see this was added with version 3.2.0:

methods() reports S4 in addition to S3 methods; output is simplified when the class 
argument is used. .S3methods() and methods::.S4methods() report S3 and S4 methods separately.

SpatialPolygons are S4 objects, and so have slots and S4-methods that are dispatched. You can display an S4 method with:

showMethods(f='plot', classes='SpatialPolygons', includeDefs=TRUE)
#    ---- result ---
Function: plot (package graphics)
x="SpatialPolygons", y="missing"
function (x, y, ...) 
plot.SpatialPolygons(x, ...)

That tells you that there is an S4 function for that class. You can execute either sp:::SpatialPolygons or getAnywhere(plot.SpatialPolygons) to see the function code. (Often that call using includeDefs=TRUE would display the R-code, but not here.) The result for methods(plot) when package 'sp' is loaded tell you that there are 8 different plot S4 methods registered in the workspace. The items following the commas are the "signatures" that are used for function dispatch. "missing-method" refers to situations where the second argument is not specified, wherein the missing function executed inside a function body would return TRUE:

  [1] plot,ANY,ANY-method                 plot,color,ANY-method              
  [3] plot,Spatial,missing-method         plot,SpatialGrid,missing-method    
  [5] plot,SpatialLines,missing-method    plot,SpatialPixels,missing-method  
  [7] plot,SpatialPoints,missing-method   plot,SpatialPolygons,missing-method

This will show you what then gets used to dispatch a plot-call when the the object passed to it does not match any of the S4 methods:

showMethods(f='plot', classes='ANY', includeDefs=TRUE)
Function: plot (package graphics)
x="ANY", y="ANY"
function (x, y, ...) 
UseMethod("plot")


x="color", y="ANY"
function (x, y, ...) 
{
    .local <- function (x, y, pch = 20, cex = 3) 
    pairs(coords(x), col = hex(x, fix = TRUE), pch = pch, cex = cex)
    .local(x, y, ...)
}

Basically the R interpreter first checks to see if any S4 methods are appropriate, and failing that, will start going through the S3 methods until it gets to plot.default.

> getMethod(f='plot', signature=c(x='SpatialPolygons', y='missing'))
Method Definition:

function (x, y, ...) 
plot.SpatialPolygons(x, ...)
<environment: namespace:sp>

Signatures:
        x                 y        
target  "SpatialPolygons" "missing"
defined "SpatialPolygons" "missing"

And BTW I see this in the response from ?getMethods:

## Deprecated in 2010 and defunct in 2015 for \code{table = FALSE}:
getMethods(f, where, table = FALSE)
like image 20
IRTFM Avatar answered Sep 28 '22 15:09

IRTFM