简介
最近有读者问我,如何查看R语言某包中某函数的源代码呢?我第一时间给出了自己比较常用的方法(见方法一),今天打算做个这方面的推文,于是又查了些资料,才发现原来水好深!还有更好的方法(见方法二),并且和不同的面向对象系统有关。
方法一
- 打开查R包的相关网站,比如:https://rdrr.io/
查R包的相关网站
- 输入你的R包名称或者相应的函数,这里以nlme包中的
lme()
为例。
找到对应位置
- 进入会出现这样的界面,界面相应介绍可以下图:
界面介绍
- 打开左上角的源代码(Source code)即可找到该包内部的所有函数了。
源代码
- 找到你对应的函数,进入即可,任务完成。
nlme源代码
方法二
Stack overflow[1]中给出了一些更加高效的方式,在R控制台输入相应函数,即可得到对应函数的源代码了。
这里小编做个知识点整理,自己也学一波。这里的知识点比较难,和面向对象编程有关,就当是拓展吧,实在不行就和小编一样使用方法一吧。
S3方法调度系统
对于S3类,可以使用methods
函数列出所有和该函数有关的特定泛型函数或类,例如:输入methods(t)
> 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”表示该函数未从其程序包的命名空间中导出。但你可以通过:::
函数(即stats :::: t.ts
)或使用getAnywhere()
查看其源代码。
注:
getAnywhere()
非常好用,你不需要知道函数来自哪个包。推荐直接使用这个函数。
> 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>
S4方法的调度系统
S4系统是一种较新的方法调度系统,可以替代S3系统。下面是一个S4函数的示例
> 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.
输出已经提供了很多信息。standardGeneric
是S4函数的指示器。使用showMethods
可以查看已定义的S4的方法
> showMethods(chol2inv) Function: chol2inv (package base) x="ANY" x="CHMfactor" x="denseMatrix" x="diagonalMatrix" x="dtrMatrix" x="sparseMatrix"
getMethod
可以用来查看其中一个方法的源代码
> getMethod("chol2inv", "diagonalMatrix") Method Definition: function (x, ...) { chk.s(...) tcrossprod(solve(x)) } <bytecode: 0x000000000ea2cc70> <environment: namespace:Matrix> Signatures: x target "diagonalMatrix" defined "diagonalMatrix"
调用未导出函数的函数
对于ts.union
,.cbindts
和.makeNamesTs
是stats名称空间中未导出的函数。您可以使用:::
运算符或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>
小编有话说
- 其实找代码简单,有些源代码是比较简单易懂的。但是更多的是通过面向对象编程的,以小编现在的能力还是看不大懂的。对于R初学者来说,要看懂源代码却是比较困难。
- 关于R语言高级编程学习,可以参考哈德利·威克汉姆开源书籍:Advanced R[2](链接在文末的参考资料中),以及机械工业出版社出了对应的中文翻译版本《高级R语言编程指南》。
- 好消息,题外话: 在导师的帮助下,小编硕士期间第一篇sci终于接受了。运气不错,投的期刊今年升为一区顶刊了。天上乌云散开了,擦擦汗水,背起行囊,继续前行。