Jos*_*ich 518 r function r-faq
我想查看一个函数的源代码,看看它是如何工作的.我知道我可以通过在提示符下键入其名称来打印函数:
> t
function (x)
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>
Run Code Online (Sandbox Code Playgroud)
在这种情况下,是什么UseMethod("t")
意思?我如何找到实际使用的源代码,例如:t(1:10)
?
有没有当我看到之间的差异UseMethod
,当我看到standardGeneric
和showMethods
,与with
?
> with
standardGeneric for "with" defined from package "base"
function (data, expr, ...)
standardGeneric("with")
<bytecode: 0x102fb3fc0>
<environment: 0x102fab988>
Methods may be defined for arguments: data
Use showMethods("with") for currently available ones.
Run Code Online (Sandbox Code Playgroud)
在其他情况下,我可以看到正在调用R函数,但我找不到这些函数的源代码.
> ts.union
function (..., dframe = FALSE)
.cbind.ts(list(...), .makeNamesTs(...), dframe = dframe, union = TRUE)
<bytecode: 0x36fbf88>
<environment: namespace:stats>
> .cbindts
Error: object '.cbindts' not found
> .makeNamesTs
Error: object '.makeNamesTs' not found
Run Code Online (Sandbox Code Playgroud)
我如何找到.cbindts
和.makeNamesTs
?一样的功能?
在其他情况下,有一些R代码,但大多数工作似乎在其他地方完成.
> matrix
function (data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
{
if (is.object(data) || !is.atomic(data))
data <- as.vector(data)
.Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow),
missing(ncol)))
}
<bytecode: 0x134bd10>
<environment: namespace:base>
> .Internal
function (call) .Primitive(".Internal")
> .Primitive
function (name) .Primitive(".Primitive")
Run Code Online (Sandbox Code Playgroud)
我如何找出该.Primitive
功能的作用?同样,一些函数调用.C
,.Call
,.Fortran
,.External
,或.Internal
.如何找到这些的源代码?
Jos*_*ich 483
UseMethod("t")
告诉你这t()
是一个(S3)泛型函数,它具有不同对象类的方法.
对于S3类,您可以使用该methods
函数列出特定泛型函数或类的方法.
> 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
Run Code Online (Sandbox Code Playgroud)
"不可见的函数带星号"表示该函数不从其包的命名空间中导出.您仍然可以通过:::
函数(即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>
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)
输出已经提供了大量信息.standardGeneric
是S4功能的指示器.有用地提供了查看定义的S4方法的方法:
> showMethods(chol2inv)
Function: chol2inv (package base)
x="ANY"
x="CHMfactor"
x="denseMatrix"
x="diagonalMatrix"
x="dtrMatrix"
x="sparseMatrix"
Run Code Online (Sandbox Code Playgroud)
getMethod
可以用来查看其中一个方法的源代码:
> getMethod("chol2inv", "diagonalMatrix")
Method Definition:
function (x, ...)
{
chk.s(...)
tcrossprod(solve(x))
}
<bytecode: 0x000000000ea2cc70>
<environment: namespace:Matrix>
Signatures:
x
target "diagonalMatrix"
defined "diagonalMatrix"
Run Code Online (Sandbox Code Playgroud)
例如,对于每种方法,还存在具有更复杂签名的方法
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"
Run Code Online (Sandbox Code Playgroud)
要查看其中一种方法的源代码,必须提供整个签名,例如
getMethod("extract" , signature = c( x = "Raster" , y = "SpatialPolygons") )
Run Code Online (Sandbox Code Playgroud)
提供部分签名是不够的
getMethod("extract",signature="SpatialPolygons")
#Error in getMethod("extract", signature = "SpatialPolygons") :
# No method found for function "extract" and signature SpatialPolygons
Run Code Online (Sandbox Code Playgroud)
在的情况下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>
Run Code Online (Sandbox Code Playgroud)
请注意,"编译"不是指由编译器包创建的字节编译的R代码.<bytecode: 0x294e410>
上面输出中的行表示该函数是字节编译的,您仍然可以从R命令行查看源.
调用功能.C
,.Call
,.Fortran
,.External
,.Internal
,或.Primitive
在编译的代码调用入口点,所以你必须看看编译代码的来源,如果你想充分了解该功能.这个 R源代码的GitHub镜像是一个不错的起点.该函数pryr::show_c_source
可以是一个有用的工具,因为它将直接带您到GitHub页面.Internal
和.Primitive
调用.包可以使用.C
,.Call
,.Fortran
,和.External
; 但不是,.Internal
或.Primitive
因为这些用于调用内置于R解释器中的函数.
调用上述某些函数可能会使用对象而不是字符串来引用已编译的函数.在这些情况下,对象是类的"NativeSymbolInfo"
,"RegisteredNativeSymbol"
或"NativeSymbol"
; 并打印对象产生有用的信息.例如,optim
电话.External2(C_optimhess, res$par, fn1, gr1, con)
(请注意C_optimhess
,不是"C_optimhess"
). optim
在stats包中,因此您可以键入stats:::C_optimhess
以查看有关正在调用的已编译函数的信息.
如果要查看包中的已编译代码,则需要下载/解压缩包源.安装的二进制文件是不够的.软件包的源代码可从最初安装软件包的相同CRAN(或CRAN兼容)存储库中获得.该download.packages()
函数可以为您获取包源.
download.packages(pkgs = "Matrix",
destdir = ".",
type = "source")
Run Code Online (Sandbox Code Playgroud)
这将下载Matrix包的源版本并将相应的.tar.gz
文件保存在当前目录中.已编译函数的源代码可以src
在未压缩和未解压缩文件的目录中找到.解压缩和解除步骤可以在函数之外R
或之内完成.可以将下载和扩展步骤组合到一个调用中(请注意,一次只能下载一个包并以这种方式解压缩):R
untar()
untar(download.packages(pkgs = "Matrix",
destdir = ".",
type = "source")[,2])
Run Code Online (Sandbox Code Playgroud)
或者,如果包开发是公开托管的(例如通过GitHub,R-Forge或RForge.net),您可以在线浏览源代码.
某些包被视为"基础"包.这些程序包随R和他们的版本被锁定到R.实例的版本包括base
,compiler
,stats
,和utils
.因此,如上所述,它们不能作为CRAN上的单独可下载包提供.相反,它们是单个包目录下的R源代码树的一部分/src/library/
.如何访问R源将在下一节中介绍.
如果要查看R解释器内置的代码,则需要下载/解压缩R源代码; 或者您可以通过R Subversion存储库或Winston Chang的github镜像在线查看源代码.
Uwe Ligges的R新闻文章(PDF)(p.43 )是如何查看源代码.Internal
和.Primitive
函数的一个很好的一般参考.基本步骤是首先查找函数名称src/main/names.c
,然后在文件中搜索"C-entry"名称src/main/*
.
smc*_*mci 93
除了这个问题及其重复的其他答案之外,这里有一个很好的方法来获取包函数的源代码,而不需要知道它所在的包.例如,如果我们想要源randomForest::rfcv()
:
要在弹出窗口中查看/编辑它:
edit(getAnywhere('rfcv'), file='source_rfcv.r')
Run Code Online (Sandbox Code Playgroud)
要重定向到单独的文件:
capture.output(getAnywhere('rfcv'), file='source_rfcv.r')
Run Code Online (Sandbox Code Playgroud)
Sel*_*lva 25
使用debug()函数进行调试时会显示它.假设您想在t()转置函数中查看底层代码.只需输入't',就不会显示太多.
>t
function (x)
UseMethod("t")
<bytecode: 0x000000003085c010>
<environment: namespace:base>
Run Code Online (Sandbox Code Playgroud)
但是,使用'debug(functionName)',它揭示了底层代码,没有内部.
> 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)
Run Code Online (Sandbox Code Playgroud)
编辑: debugonce()完成相同,而不必使用undebug()
Geo*_*ole 19
对于非原始函数,R base包含一个body()
返回函数体的函数.例如,print.Date()
可以查看函数的来源:
body(print.Date)
Run Code Online (Sandbox Code Playgroud)
会产生这个:
{
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)
}
Run Code Online (Sandbox Code Playgroud)
如果您正在使用脚本并希望将函数代码作为字符向量,则可以获取它.
capture.output(print(body(print.Date)))
Run Code Online (Sandbox Code Playgroud)
会得到你:
[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] "}"
Run Code Online (Sandbox Code Playgroud)
我为什么要做这样的事情?我正在基于列表创建自定义S3对象(x
,where class(x) = "foo"
).其中一个列表成员(名为"fun")是一个函数,我想print.foo()
显示函数源代码,缩进.所以我最终得到了以下片段print.foo()
:
sourceVector = capture.output(print(body(x[["fun"]])))
cat(paste0(" ", sourceVector, "\n"))
Run Code Online (Sandbox Code Playgroud)
缩进并显示与之关联的代码x[["fun"]]
.
Mic*_*ico 18
没有看到这是如何适应主要答案的流程但它让我困扰了一段时间所以我在这里添加它:
看到一些碱中缀运算符(例如,源代码%%
,%*%
,%in%
),使用getAnywhere
,例如:
getAnywhere("%%")
# A single object matching ‘%%’ was found
# It was found in the following places
# package:base
# namespace:base
# with value
#
# function (e1, e2) .Primitive("%%")
Run Code Online (Sandbox Code Playgroud)
主要答案包括如何使用镜子深入挖掘.
Eri*_*ric 10
R中有一个非常方便的功能 edit
new_optim <- edit(optim)
Run Code Online (Sandbox Code Playgroud)
它将打开optim
使用R中指定的编辑器的源代码options
,然后您可以编辑它并将修改后的函数分配给new_optim
.我非常喜欢这个函数来查看代码或调试代码,例如,打印一些消息或变量,甚至将它们分配给全局变量以供进一步调查(当然你可以使用debug
).
如果您只想查看源代码并且不希望在控制台上打印恼人的长源代码,则可以使用
invisible(edit(optim))
Run Code Online (Sandbox Code Playgroud)
显然,这不能用于查看C/C++或Fortran源代码.
BTW,edit
可以打开列表,矩阵等其他对象,然后显示具有属性的数据结构.函数de
可用于打开类似编辑器的excel(如果GUI支持它)来修改矩阵或数据框并返回新的.这有时很方便,但在通常情况下应该避免,特别是当矩阵很大时.
只要该函数是用纯R而不是C/C++/Fortran编写的,就可以使用以下内容.否则最好的方法是调试并使用" jump into ":
> functionBody(functionName)
Run Code Online (Sandbox Code Playgroud)
您也可以尝试使用print.function()
S3通用的来在控制台中编写函数。
在RStudio中,至少有3种方式:
View
(function_name)(如上所述)将打开一个包含源代码的新窗格。如果您达到.Primitive或.C,则需要另一种方法,对不起。
归档时间: |
|
查看次数: |
259186 次 |
最近记录: |