李哲源*_*李哲源 6 methods r function
我知道我可以列出所有S3方法为特定的通用功能,比如说summary
,由
.S3methods("summary")
# [1] summary.aov summary.aovlist*
# [3] summary.aspell* summary.check_packages_in_dir*
# [5] summary.connection summary.data.frame
# [7] summary.Date summary.default
# [9] summary.ecdf* summary.factor
#[11] summary.glm summary.infl*
#[13] summary.lm summary.loess*
#[15] summary.manova summary.matrix
#[17] summary.mlm* summary.nls*
#[19] summary.packageStatus* summary.PDF_Dictionary*
#[21] summary.PDF_Stream* summary.POSIXct
#[23] summary.POSIXlt summary.ppr*
#[25] summary.prcomp* summary.princomp*
#[27] summary.proc_time summary.srcfile
#[29] summary.srcref summary.stepfun
#[31] summary.stl* summary.table
#[33] summary.tukeysmooth*
Run Code Online (Sandbox Code Playgroud)
但是,我知道其中一些功能来自stats
,而一些来自base
.如果我将更多的包加载到R中,则此列表可能会更长.因此,我想限制特定包/命名空间中的搜索,但我找不到这样做的方法.
该手册?.S3methods
似乎是自相矛盾的.
.S3methods(generic.function, class, envir=parent.frame())
envir: the environment in which to look for the definition of the
generic function, when the generic function is passed as a
character string.
Run Code Online (Sandbox Code Playgroud)
所以我尝试了以下但仍然显示所有方法:
.S3methods("summary", envir = getNamespace("base"))
Run Code Online (Sandbox Code Playgroud)
在手册的"详细信息"部分,有人说:
'methods()'找到与'generic.function'或'class'参数相关的S3和S4方法.在当前"search()"路径的所有包中都可以找到方法.'.S3methods()'只找到S3方法,'.S4methods()'只找到S4方法.
所以基本上它否认了论证的使用envir
.
无论如何,我可以实现有限的搜索和显示.
MrFlick的回答(现在很遗憾被删除)非常有帮助.忘记检查返回的值是我的错.S3methods
.但是,他的回答并没有完全解决问题.
xx <- .S3methods("summary")
yy <- attr(xx, "info")
levels(yy$from)
#[1] "base" "datasets"
#[3] ".GlobalEnv" "graphics"
#[5] "grDevices" "methods"
#[7] "stats" "utils"
#[9] "registered S3method for summary"
Run Code Online (Sandbox Code Playgroud)
级别"注册的S3方法摘要"是相当模糊的.使用这种方法,只能stats
显示包中的5个结果:
xx[yy$from == "stats"]
#[1] "summary.aov" "summary.glm" "summary.lm" "summary.manova"
#[5] "summary.stepfun"
Run Code Online (Sandbox Code Playgroud)
在我发布这个问题之后,我意识到通过正则表达式有一种方法.这表明实际上有16次点击.
grep("^summary.", ls(getNamespace("stats")), value = TRUE)
# [1] "summary.aov" "summary.aovlist" "summary.ecdf"
# [4] "summary.glm" "summary.infl" "summary.lm"
# [7] "summary.loess" "summary.manova" "summary.mlm"
#[10] "summary.nls" "summary.ppr" "summary.prcomp"
#[13] "summary.princomp" "summary.stepfun" "summary.stl"
#[16] "summary.tukeysmooth"
Run Code Online (Sandbox Code Playgroud)
所以在找到任何替代解决方案之前,我会继续使用正则表达式.这是一个功能.
## provide (generic) function name and package name as strings
findS3Fun <- function (Fun, pkg) {
all_fun <- ls(getNamespace(pkg))
all_fun[startsWith(all_fun, sprintf("%s.", Fun))]
}
findS3Fun("summary", "stats")
Run Code Online (Sandbox Code Playgroud)
findS3Fun
实际上是马车.
findS3Fun("seq", "base")
#[1] "seq.Date" "seq.default" "seq.int" "seq.POSIXt"
findS3Fun("sort", "base")
#[1] "sort.default" "sort.int" "sort.list" "sort.POSIXlt"
Run Code Online (Sandbox Code Playgroud)
seq.int
不是"int"方法seq
.无论是sort.int
也不sort.list
是"INT"或"名单"的方法sort
.它们只是.
功能名称中的独立功能.
.S3methods("seq")
#[1] seq.Date seq.default seq.POSIXt
.S3methods("sort")
#[1] sort.bibentry* sort.default sort.POSIXlt
## this function is from package `utils` not `base`
environment(getS3method("sort", "bibentry"))
#<environment: namespace:utils>
Run Code Online (Sandbox Code Playgroud)
所以最安全的方法可能仍然是使用返回的值.S3methods
.
getAnywhere
(getS3method
)回到"摘要"的例子.不是从命名空间,即那些有导出的函数yy$visible = FALSE
,有yy$from = "registered S3method for summary"
.
with(yy, from[!visible])
# [1] registered S3method for summary registered S3method for summary
# [3] registered S3method for summary registered S3method for summary
# [5] registered S3method for summary registered S3method for summary
# [7] registered S3method for summary registered S3method for summary
# [9] registered S3method for summary registered S3method for summary
#[11] registered S3method for summary registered S3method for summary
#[13] registered S3method for summary registered S3method for summary
#[15] registered S3method for summary registered S3method for summary
#8 Levels: base datasets graphics grDevices methods stats ... registered S3method for summary
Run Code Online (Sandbox Code Playgroud)
但是,既然我们知道这些功能的名称,为什么不适用getAnywhere
它们呢?
zz <- lapply(xx[!yy$visible], getAnywhere)
Run Code Online (Sandbox Code Playgroud)
然后可以通过zz
一些努力来提取包/命名空间信息.但是,这个lapply
+ getAnywhere
非常慢.由于getAnywhere
返回的内容超出了我的需要,我挖掘了它的源代码,看看我是否可以做一些修剪.事实证明我可以.
hidden <- xx[!yy$visible]
# [1] "summary.aovlist" "summary.aspell"
# [3] "summary.check_packages_in_dir" "summary.ecdf"
# [5] "summary.infl" "summary.loess"
# [7] "summary.mlm" "summary.nls"
# [9] "summary.packageStatus" "summary.PDF_Dictionary"
#[11] "summary.PDF_Stream" "summary.ppr"
#[13] "summary.prcomp" "summary.princomp"
#[15] "summary.stl" "summary.tukeysmooth"
CLASS <- substr(hidden, nchar("summary") + 2L, nchar(hidden))
#[1] "aovlist" "aspell" "check_packages_in_dir"
# [4] "ecdf" "infl" "loess"
# [7] "mlm" "nls" "packageStatus"
#[10] "PDF_Dictionary" "PDF_Stream" "ppr"
#[13] "prcomp" "princomp" "stl"
#[16] "tukeysmooth"
vapply(CLASS,
function (u) getNamespaceName(environment(getS3method("summary", u)))[[1L]],
"", USE.NAMES = FALSE)
# [1] "stats" "utils" "tools" "stats" "stats" "stats" "stats" "stats" "utils"
#[10] "tools" "tools" "stats" "stats" "stats" "stats" "stats"
Run Code Online (Sandbox Code Playgroud)
现在让我将这些想法结合到一个函数中.
findS3Fun <- function (Fun, pkg) {
xx <- .S3methods(Fun)
yy <- attr(xx, "info")[1:2]
where <- yy[[2L]] ## yy$from
where <- levels(where)[where] ## factor to character
hidden <- !yy[[1L]] ## !yy$visible
hidden_xx <- xx[hidden] ## hidden functions
if (length(hidden) > 0L) {
CLASS <- substr(hidden_xx, nchar(Fun) + 2L, nchar(hidden_xx))
aux <- function (u) getNamespaceName(environment(getS3method(Fun, u)))[[1L]]
where[hidden] <- vapply(CLASS, aux, "", USE.NAMES = FALSE)
}
export <- where == pkg
xx <- xx[export]
visible <- yy[[1L]][export]
## use "regex" to find functions with "." in their names but not methods
all_fun <- ls(getNamespace(pkg))
all_fun <- all_fun[startsWith(all_fun, sprintf("%s.", Fun))]
misc <- all_fun[!(all_fun %in% xx)]
## return functions by category
list(visible = xx[visible], invisible = xx[!visible], misc = misc)
}
Run Code Online (Sandbox Code Playgroud)
最后,我仍然使用正则表达式来捕获.
其名称中的函数,但这些函数不是正确的方法.除了"可见"和"隐形"之外,它们被归类为"misc".
findS3Fun("summary", "stats")
#$visible
#[1] "summary.aov" "summary.glm" "summary.lm" "summary.manova"
#[5] "summary.stepfun"
#
#$invisible
# [1] "summary.aovlist" "summary.ecdf" "summary.infl"
# [4] "summary.loess" "summary.mlm" "summary.nls"
# [7] "summary.ppr" "summary.prcomp" "summary.princomp"
#[10] "summary.stl" "summary.tukeysmooth"
#
#$misc
#character(0)
Run Code Online (Sandbox Code Playgroud)
findS3Fun("sort", "base")
#$visible
#[1] "sort.default" "sort.POSIXlt"
#
#$invisible
#character(0)
#
#$misc
#[1] "sort.int" "sort.list"
Run Code Online (Sandbox Code Playgroud)
findS3Fun("[", "base")
#$visible
# [1] "[.AsIs" "[.data.frame" "[.Date"
# [4] "[.difftime" "[.Dlist" "[.factor"
# [7] "[.hexmode" "[.listof" "[.noquote"
#[10] "[.numeric_version" "[.octmode" "[.POSIXct"
#[13] "[.POSIXlt" "[.simple.list" "[.table"
#[16] "[.warnings"
#
#$invisible
#character(0)
#
#$misc
#character(0)
Run Code Online (Sandbox Code Playgroud)
findS3Fun("[[", "base")
#$visible
#[1] "[[.data.frame" "[[.Date" "[[.factor"
#[4] "[[.numeric_version" "[[.POSIXct"
#
#$invisible
#character(0)
#
#$misc
#character(0)
Run Code Online (Sandbox Code Playgroud)