R 如何查看函数的源代码?

R 如何查看函数的源代码?,r,function,r-faq,R,Function,R Faq,我想看看函数的源代码,看看它是如何工作的。我知道我可以通过在提示符处键入函数名来打印函数: > t function (x) UseMethod("t") <bytecode: 0x2332948> <environment: namespace:base> 在其他情况下,我可以看到正在调用R函数,但我找不到这些函数的源代码 > ts.union function (..., dframe = FALSE) .cbind.ts(list(...), .m

我想看看函数的源代码,看看它是如何工作的。我知道我可以通过在提示符处键入函数名来打印函数:

> t
function (x) 
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>
在其他情况下,我可以看到正在调用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
如何找到
.Primitive
函数的功能?类似地,有些函数调用
.C
.call
.Fortran
.External
.Internal
。如何找到这些函数的源代码?

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
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.
getMethod
可用于查看以下方法之一的源代码:

> getMethod("chol2inv", "diagonalMatrix")
Method Definition:

function (x, ...) 
{
    chk.s(...)
    tcrossprod(solve(x))
}
<bytecode: 0x000000000ea2cc70>
<environment: namespace:Matrix>

Signatures:
        x               
target  "diagonalMatrix"
defined "diagonalMatrix"
要查看这些方法之一的源代码,必须提供完整的签名,例如

getMethod("extract" , signature = c( x = "Raster" , y = "SpatialPolygons") )
仅提供部分签名是不够的

getMethod("extract",signature="SpatialPolygons")
#Error in getMethod("extract", signature = "SpatialPolygons") : 
#  No method found for function "extract" and signature SpatialPolygons
调用未报告函数的函数 在
ts.union
的情况下,
.cbindts
makenamets
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>
这将下载Matrix软件包的源版本,并将相应的
.tar.gz
文件保存在当前目录中。编译函数的源代码可以在未压缩和未编译文件的
src
目录中找到。解压和解压步骤可以在
R
之外完成,也可以使用
untar()
功能从
R
内部完成。可以将下载和扩展步骤合并到单个调用中(注意,一次只能下载和解包一个包):

或者,如果包开发是公开托管的(例如,通过或),您可能可以在线浏览源代码

基本包中的编译代码 某些包被视为“基本”包。这些包随R一起提供,其版本锁定为R的版本。示例包括
base
compiler
stats
utils
。因此,如上所述,它们不能在CRAN上作为单独的可下载包提供。相反,它们是
/src/library/
下各个包目录中R源代码树的一部分。下一节将介绍如何访问R源

编译后的代码内置于R解释器中 如果您想查看R解释器内置的代码,则需要下载/解包R源代码;或者您可以通过R或在线查看来源


Uwe-Ligges(第43页)是一个很好的关于如何查看
.Internal
.Primitive
函数源代码的一般参考。基本步骤是首先在
src/main/names.c
中查找函数名,然后在
src/main/*

中的文件中搜索“c条目”名,以及关于此问题的其他答案及其副本,下面是一种获取包函数源代码的好方法,无需知道它在哪个包中。 e、 g.说如果我们想要
随机森林::rfcv()的源代码:

要在弹出窗口中查看/编辑它,请执行以下操作: 请注意,
edit()
打开一个文本编辑器(由用户选择),而
View()
调用电子表格样式的数据查看器

  • View()
  • 因此,当只想查看代码时,
    edit()
    实际上比
    view()
    好得多,因为使用
    edit()
    可以折叠/隐藏/伪造所有参数解析/检查/默认/错误消息逻辑,这些逻辑可能占R函数的70%,只需进入函数实际执行操作的部分(!),返回类型是什么类型的对象,是否递归以及如何递归,等等
重定向到一个单独的文件(这样你就可以在你喜欢的IDE/编辑器中打开代码/用grep/等处理代码):
当您使用debug()函数进行调试时,它会显示出来。 假设您希望在t()转置函数中看到底层代码。仅仅输入“t”并不能透露太多信息

>t 
function (x) 
UseMethod("t")
<bytecode: 0x000000003085c010>
<environment: namespace:base>
>t
功能(x)
使用方法(“t”)
但是,使用“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)
调试(t) >t(二氧化碳) 调试时间:t(co2) 调试:使用方法(“t”) 浏览[2]> 调试时间:t.ts(co2) 调试:{
cl在R
编辑中有一个非常方便的功能

new_optim <- edit(optim)
显然,这不能用于查看C/C++或Fortran源代码


顺便说一句,
edit
可以打开列表、矩阵等其他对象,然后显示带有属性的数据结构。Function
de
可以用于打开类似excel的编辑器(如果GUI支持)修改矩阵或数据框并返回新的矩阵或数据框。这有时很方便,但在通常情况下应该避免,尤其是当矩阵很大时。

没有看到这与主要答案的流程有什么关系,但它让我困惑了一段时间,因此我在这里添加它:

中缀运算符 要查看某些基本中缀运算符的源代码(例如,
%%
%%*%%
%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("%%")

主要答案包括如何使用镜像进行深入挖掘。

对于非基本函数,R base包含一个名为
body()的函数<
> 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>
download.packages(pkgs = "Matrix", 
                  destdir = ".",
                  type = "source")
untar(download.packages(pkgs = "Matrix",
                        destdir = ".",
                        type = "source")[,2])
edit(getAnywhere('rfcv'), file='source_rfcv.r')

View(getAnywhere('rfcv'), file='source_rfcv.r')
capture.output(getAnywhere('rfcv'), file='source_rfcv.r')
>t 
function (x) 
UseMethod("t")
<bytecode: 0x000000003085c010>
<environment: namespace:base>
> 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)
new_optim <- edit(optim)
invisible(edit(optim))
getAnywhere("%%")
# A single object matching ‘%%’ was found
# It was found in the following places
#   package:base
#   namespace:base
#  with value
#
# function (e1, e2)  .Primitive("%%")
body(print.Date)
{
    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)
}
capture.output(print(body(print.Date)))
[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] "}"     
sourceVector = capture.output(print(body(x[["fun"]])))
cat(paste0("      ", sourceVector, "\n"))
sourceVector = deparse(body(x$fun))
> functionBody(functionName)