Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 如何查看函数的源代码?_R_Function_R Faq - Fatal编程技术网

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。如何找到这些函数的源代码?

UseMethodt告诉您,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查看未报告函数的源代码

这将下载Matrix包的源版本,并将相应的.tar.gz文件保存在当前目录中。编译函数的源代码可以在未压缩和未编译文件的src目录中找到。解压和解压步骤可以在R外部完成,也可以使用untar函数从R内部完成。可以将下载和扩展步骤合并到一个呼叫通知中,一次只能下载和解包一个软件包:

untar(download.packages(pkgs = "Matrix",
                        destdir = ".",
                        type = "source")[,2])
或者,如果包开发是公开托管的,例如通过,或者,您可能可以在线浏览源代码

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

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


Uwe Ligges's p。43是关于如何查看.Internal和.Primitive函数的源代码的一个很好的通用参考。基本步骤是首先在src/main/names.c中查找函数名,然后在src/main/*中的文件中搜索c-entry名称。

除了这个问题的其他答案及其副本之外,下面是一个获取包函数源代码的好方法,而无需知道它在哪个包中。 e、 g.如果我们想要randomForest::rfcv的源:

要在弹出窗口中查看/编辑它,请执行以下操作: 请注意,“编辑”将打开用户选择的文本编辑器,而 视图调用电子表格样式的数据查看器

View非常适合浏览多栏数据,但通常不适合任何长度的代码。 因此,当只想查看代码时,edit实际上要比view好得多,因为通过edit,您可以折叠/隐藏/虚化所有arg解析/检查/默认/错误消息逻辑,这些逻辑可能占R函数的70%,只需进入函数实际操作的部分即可!,它的返回类型是什么类型的对象,是否以及如何递归等。 要重定向到一个单独的文件,以便您可以在您喜爱的IDE/编辑器/使用grep/etc处理代码,请执行以下操作:
当您使用debug函数进行调试时,它会显示出来。 假设您想在t转置函数中看到底层代码。仅仅输入“t”并不能透露太多信息

>t 
function (x) 
UseMethod("t")
<bytecode: 0x000000003085c010>
<environment: namespace:base>
但是,使用“debugfunctionName”,它揭示了底层代码,而没有内部代码

> 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)
编辑:
debugonce无需使用undebug即可实现相同的功能,R edit中有一个非常方便的功能

显然,这不能用于查看C/C++或Fortran源代码


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

没有看到这与主要答案的流程是如何匹配的,但它让我困惑了一段时间,所以我在这里添加它:

中缀运算符 要查看一些基本中缀运算符的源代码,例如%%、%*%、%in%,请使用getA 纽约,例如:


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

对于非基本函数,R base包含一个名为body的函数,该函数返回函数体。例如,可以查看print.Date函数的来源:

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)
}
将为您提供:

[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] "}"     
缩进并显示与x[[fun]]关联的代码

编辑2020-12-31

获得源代码相同字符向量的一种不太迂回的方法是:

sourceVector = deparse(body(x$fun))

Viewfunction_name-例如Viewmean确保使用大写字母[V]。只读代码将在编辑器中打开。

只要函数是用纯R而不是C/C++/Fortran编写的,就可以使用以下方法。否则,最好的方法是调试并使用跳转:


您还可以尝试使用S3通用的print.function在控制台中写入函数。

在RStudio中,至少有3种方法:

当光标位于任何功能上时,按F2键。 按住键的同时单击函数名 Ctrl或Command Viewfunction_名称如上所述
将打开一个包含源代码的新窗格。如果使用.Primitive或.C,则需要另一种方法,抱歉。

另请参见如果使用RStudio,则按F2键时,文本光标所在函数的源代码将被拉入。@Ari B.Friedman对于这个迟来的问题表示抱歉。RStudio是否也会为函数提取C源代码,还是仅仅为用R编写的函数提取C源代码?Thanks@Samir我相信这只是R源。@AriB.Friedman-谢谢Ari,这很方便。在我的例子中,我仍然需要答案量表中显示的知识,即S3-我获得了UseMethodscale,然后使用GetAnywhere scale.default。但是简单的函数工作得很好。模仿是最真诚的恭维形式,我认为这个答案/维基是第一位的:在此之前,与公认答案中给出的方法相比,这种方法的缺点是,你需要一个工作函数调用所有必要的参数,这些参数都是可以接受的;除了最初的代码块,您还可以在运行每个代码块时获得它。这对于调试来说是很好的,但是对于获取源代码来说并不是最优的。但是如果你聪明的话,你可以快速地获取源代码,特别是对于内置函数。我还建议在本例中使用debugonce而不是debug。这种方法只会产生与打印函数相同的函数源代码,这与问题中的相同。这个问题的目的是为了进一步/深入。@BrianDiggs是的,你是对的。我本不想回答这个问题,因为约书亚已经给出了一个相当完整的答案。我只是试着添加一些与主题相关的东西,有趣的,可能有用的了解。对不起,我已经在7个月前发布了这篇文章。不可见项的使用。。。不过,这是一个很好的提示,而且这句话在C/C++或Fortran上也不起作用。无可否认,getAnywhere是另一个古怪的R名称选择,它本应被称为findOnSearchPath或类似名称。我将投票支持这个答案,因为它让我接近了我想要的。在RStudio中,我真正想要的是Viewfoo;其中foo是一个已经加载的包中的函数。@Sigfried:,而后者适合于浏览多列数据,但通常对于除toy长度以外的任何代码都很糟糕。例如,正如我所提示的,通常在浏览函数时,我要做的第一件事是跳过/折叠/虚化所有参数解析和默认操作逻辑,以查看函数的实际功能。@Sigfried:已更新以合并所有这些备注/提示。推荐去任何地方。或者,如果您已经知道运算符的名称,`%in%`,则可以使用backticks。@JoshuaUlrich不知道您可以使用backticks!谢谢你的回答中也提到了getAnywhere,但我认为中缀的具体引用对于这个答案的未来参考是有用的-我已经阅读了很多次这一页,并且在试图找到这些函数的代码时仍然有点困惑-我认为它不适合任何其他答案的流程,这两个答案都使用getAnywhere用于其他目的。这与body是一样的。identicalfunctionBody,body为TRUE。base::body和methods::functionBody,尽管它们不需要详细说明。body也可以被重写:print.function是一个S3方法。通用的是打印。直接调用方法通常不是一个好主意。这违背了泛型函数和方法分派的全部目的。
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)