r - How can I view the source code for a function?

ID : 3144

viewed : 111

Tags : rfunctionr-faqr

Top 5 Answer for r - How can I view the source code for a function?

vote vote

90

UseMethod("t") is telling you that t() is a (S3) generic function that has methods for different object classes.

The S3 method dispatch system

For S3 classes, you can use the methods function to list the methods for a particular generic function or class.

> methods(t) [1] t.data.frame t.default    t.ts*            Non-visible functions are asterisked > methods(class="ts")  [1] aggregate.ts     as.data.frame.ts cbind.ts*        cycle.ts*         [5] diffinv.ts*      diff.ts          kernapply.ts*    lines.ts          [9] monthplot.ts*    na.omit.ts*      Ops.ts*          plot.ts          [13] print.ts         time.ts*         [<-.ts*          [.ts*            [17] t.ts*            window<-.ts*     window.ts*           Non-visible functions are asterisked 

"Non-visible functions are asterisked" means the function is not exported from its package's namespace. You can still view its source code via the ::: function (i.e. stats:::t.ts), or by using getAnywhere(). getAnywhere() is useful because you don't have to know which package the function came from.

> getAnywhere(t.ts) A single object matching ‘t.ts’ was found It was found in the following places   registered S3 method for t from namespace stats   namespace:stats with value  function (x)  {     cl <- oldClass(x)     other <- !(cl %in% c("ts", "mts"))     class(x) <- if (any(other))          cl[other]     attr(x, "tsp") <- NULL     t(x) } <bytecode: 0x294e410> <environment: namespace:stats> 

The S4 method dispatch system

The S4 system is a newer method dispatch system and is an alternative to the S3 system. Here is an example of an S4 function:

> library(Matrix) Loading required package: lattice > chol2inv standardGeneric for "chol2inv" defined from package "base"  function (x, ...)  standardGeneric("chol2inv") <bytecode: 0x000000000eafd790> <environment: 0x000000000eb06f10> Methods may be defined for arguments: x Use  showMethods("chol2inv")  for currently available ones. 

The output already offers a lot of information. standardGeneric is an indicator of an S4 function. The method to see defined S4 methods is offered helpfully:

> showMethods(chol2inv) Function: chol2inv (package base) x="ANY" x="CHMfactor" x="denseMatrix" x="diagonalMatrix" x="dtrMatrix" x="sparseMatrix" 

getMethod can be used to see the source code of one of the methods:

> getMethod("chol2inv", "diagonalMatrix") Method Definition:  function (x, ...)  {     chk.s(...)     tcrossprod(solve(x)) } <bytecode: 0x000000000ea2cc70> <environment: namespace:Matrix>  Signatures:         x                target  "diagonalMatrix" defined "diagonalMatrix" 

There are also methods with more complex signatures for each method, for example

require(raster) showMethods(extract) Function: extract (package raster) x="Raster", y="data.frame" x="Raster", y="Extent" x="Raster", y="matrix" x="Raster", y="SpatialLines" x="Raster", y="SpatialPoints" x="Raster", y="SpatialPolygons" x="Raster", y="vector" 

To see the source code for one of these methods the entire signature must be supplied, e.g.

getMethod("extract" , signature = c( x = "Raster" , y = "SpatialPolygons") ) 

It will not suffice to supply the partial signature

getMethod("extract",signature="SpatialPolygons") #Error in getMethod("extract", signature = "SpatialPolygons") :  #  No method found for function "extract" and signature SpatialPolygons 

Functions that call unexported functions

In the case of ts.union, .cbindts and .makeNamesTs are unexported functions from the stats namespace. You can view the source code of unexported functions by using the ::: operator or getAnywhere.

> stats:::.makeNamesTs function (...)  {     l <- as.list(substitute(list(...)))[-1L]     nm <- names(l)     fixup <- if (is.null(nm))          seq_along(l)     else nm == ""     dep <- sapply(l[fixup], function(x) deparse(x)[1L])     if (is.null(nm))          return(dep)     if (any(fixup))          nm[fixup] <- dep     nm } <bytecode: 0x38140d0> <environment: namespace:stats> 

Functions that call compiled code

Note that "compiled" does not refer to byte-compiled R code as created by the compiler package. The <bytecode: 0x294e410> line in the above output indicates that the function is byte-compiled, and you can still view the source from the R command line.

Functions that call .C, .Call, .Fortran, .External, .Internal, or .Primitive are calling entry points in compiled code, so you will have to look at sources of the compiled code if you want to fully understand the function. This GitHub mirror of the R source code is a decent place to start. The function pryr::show_c_source can be a useful tool as it will take you directly to a GitHub page for .Internal and .Primitive calls. Packages may use .C, .Call, .Fortran, and .External; but not .Internal or .Primitive, because these are used to call functions built into the R interpreter.

Calls to some of the above functions may use an object instead of a character string to reference the compiled function. In those cases, the object is of class "NativeSymbolInfo", "RegisteredNativeSymbol", or "NativeSymbol"; and printing the object yields useful information. For example, optim calls .External2(C_optimhess, res$par, fn1, gr1, con) (note that's C_optimhess, not "C_optimhess"). optim is in the stats package, so you can type stats:::C_optimhess to see information about the compiled function being called.

Compiled code in a package

If you want to view compiled code in a package, you will need to download/unpack the package source. The installed binaries are not sufficient. A package's source code is available from the same CRAN (or CRAN compatible) repository that the package was originally installed from. The download.packages() function can get the package source for you.

download.packages(pkgs = "Matrix",                    destdir = ".",                   type = "source") 

This will download the source version of the Matrix package and save the corresponding .tar.gz file in the current directory. Source code for compiled functions can be found in the src directory of the uncompressed and untared file. The uncompressing and untaring step can be done outside of R, or from within R using the untar() function. It is possible to combine the download and expansion step into a single call (note that only one package at a time can be downloaded and unpacked in this way):

untar(download.packages(pkgs = "Matrix",                         destdir = ".",                         type = "source")[,2]) 

Alternatively, if the package development is hosted publicly (e.g. via GitHub, R-Forge, or RForge.net), you can probably browse the source code online.

Compiled code in a base package

Certain packages are considered "base" packages. These packages ship with R and their version is locked to the version of R. Examples include base, compiler, stats, and utils. As such, they are not available as separate downloadable packages on CRAN as described above. Rather, they are part of the R source tree in individual package directories under /src/library/. How to access the R source is described in the next section.

Compiled code built into the R interpreter

If you want to view the code built-in to the R interpreter, you will need to download/unpack the R sources; or you can view the sources online via the R Subversion repository or Winston Chang's github mirror.

Uwe Ligges's R news article (PDF) (p. 43) is a good general reference of how to view the source code for .Internal and .Primitive functions. The basic steps are to first look for the function name in src/main/names.c and then search for the "C-entry" name in the files in src/main/*.

vote vote

87

In addition to the other answers on this question and its duplicates, here's a good way to get source code for a package function without needing to know which package it's in. e.g. say if we want the source for randomForest::rfcv():

To view/edit it in a pop-up window:

edit(getAnywhere('rfcv'), file='source_rfcv.r')  View(getAnywhere('rfcv'), file='source_rfcv.r') 

Note that edit() opens a text editor (of user's choice), whereas View() invokes a spreadsheet-style data viewer.

  • View() is great for browsing (multi-columnar) data, but usually terrible for code of anything other than toy length.
  • so when only want to view code, edit() is IMO actually far better than View(), since with edit() you can collapse/hide/dummy out all the arg-parsing/checking/default/error-message logic which can take up to 70% of an R function, and just get to the part where the function actually operationally does something(!), what type(s) of objects its return type is, whether and how it recurses, etc.

To redirect to a separate file (so you can bring up the code in your favorite IDE/editor/process it with grep/etc.):

capture.output(getAnywhere('rfcv'), file='source_rfcv.r') 
vote vote

73

It gets revealed when you debug using the debug() function. Suppose you want to see the underlying code in t() transpose function. Just typing 't', doesn't reveal much.

>t  function (x)  UseMethod("t") <bytecode: 0x000000003085c010> <environment: namespace:base> 

But, Using the 'debug(functionName)', it reveals the underlying code, sans the internals.

> debug(t) > t(co2) debugging in: t(co2) debug: UseMethod("t") Browse[2]>  debugging in: t.ts(co2) debug: {     cl <- oldClass(x)     other <- !(cl %in% c("ts", "mts"))     class(x) <- if (any(other))          cl[other]     attr(x, "tsp") <- NULL     t(x) } Browse[3]>  debug: cl <- oldClass(x) Browse[3]>  debug: other <- !(cl %in% c("ts", "mts")) Browse[3]>  debug: class(x) <- if (any(other)) cl[other] Browse[3]>   debug: attr(x, "tsp") <- NULL Browse[3]>  debug: t(x) 

EDIT: debugonce() accomplishes the same without having to use undebug()

vote vote

67

For non-primitive functions, R base includes a function called body() that returns the body of function. For instance the source of the print.Date() function can be viewed:

body(print.Date) 

will produce this:

{     if (is.null(max))          max <- getOption("max.print", 9999L)     if (max < length(x)) {         print(format(x[seq_len(max)]), max = max, ...)         cat(" [ reached getOption(\"max.print\") -- omitted",              length(x) - max, "entries ]\n")     }     else print(format(x), max = max, ...)     invisible(x) } 

If you are working in a script and want the function code as a character vector, you can get it.

capture.output(print(body(print.Date))) 

will get you:

[1] "{"                                                                    [2] "    if (is.null(max)) "                                               [3] "        max <- getOption(\"max.print\", 9999L)"                       [4] "    if (max < length(x)) {"                                           [5] "        print(format(x[seq_len(max)]), max = max, ...)"               [6] "        cat(\" [ reached getOption(\\\"max.print\\\") -- omitted\", " [7] "            length(x) - max, \"entries ]\\n\")"                       [8] "    }"                                                                [9] "    else print(format(x), max = max, ...)"                            [10] "    invisible(x)"                                                     [11] "}"      

Why would I want to do such a thing? I was creating a custom S3 object (x, where class(x) = "foo") based on a list. One of the list members (named "fun") was a function and I wanted print.foo() to display the function source code, indented. So I ended up with the following snippet in print.foo():

sourceVector = capture.output(print(body(x[["fun"]]))) cat(paste0("      ", sourceVector, "\n")) 

which indents and displays the code associated with x[["fun"]].

Edit 2020-12-31

A less circuitous way to get the same character vector of source code is:

sourceVector = deparse(body(x$fun)) 
vote vote

53

Didn't see how this fit into the flow of the main answer but it stumped me for a while so I'm adding it here:

Infix Operators

To see the source code of some base infix operators (e.g., %%, %*%, %in%), use getAnywhere, e.g.:

getAnywhere("%%") # A single object matching ‘%%’ was found # It was found in the following places #   package:base #   namespace:base #  with value # # function (e1, e2)  .Primitive("%%") 

The main answer covers how to then use mirrors to dig deeper.

Top 3 video Explaining r - How can I view the source code for a function?

Related QUESTION?