R包函数源码查询

家和建材广场:联系电话-0373-7621288

位置:河南省新乡市延津县人民路与西环路交叉口向东100米路北。

有家和幸福生活!

原网址:https://wenda.so.com/q/1532798392213322

在r中看函数源代码:

在R中,代码可以分为如下几个级别:

首先,是你输入了函数对象名称,你可以直接看到代码的,如要获得函数对象fivenum的代码,就只需要在Console中键入函数对象名称fivenum就可以得到如下结果:

function (x, na.rm = TRUE)

{

xna <- is.na(x)

if (na.rm)

x <- x[!xna]

else if (any(xna))

return(rep.int(NA, 5))

x <- sort(x)

n <- length(x)

if (n == 0)

rep.int(NA, 5)

else {

n4 <- floor((n + 3)/2)/2

d <- c(1, n4, (n + 1)/2, n + 1 - n4, n)

0.5 * (x[floor(d)] + x[ceiling(d)])

}

}

<environment: namespace:stats>

从上面的例子可以看出,这类函数对象的代码是最容易看到的,也是我们学习的最好的材料了,而R中最大多数的函数对象是以这种方式出现的。

其次,我们在输入mean这类函数名次的时候,会出现如下结果:

function (x, ...)

UseMethod("mean")

<environment: namespace:base>

这表示函数作者把函数“封”起来了。这个时候我们可以先试一试methods(mean),利用methods函数看看mean这个函数都有哪些类型的,我们得到的结果如下:

[1] mean.data.frame mean.Date      mean.default    mean.difftime  mean.POSIXct  mean.POSIXlt

其实对此可以有一个简单的理解,虽然不够精确。因为在R中,mean函数可以求得属于不同类型对象的平均值,而不同类型对象平均值的求法还是有一些小小差 异的,比如说求一个向量的平均值和求一个数据框的平均值就有所差异,就要编写多个mean函数,然后“封”起来,以一个统一的mean出现,方便我们使 用。这正好也反映了R有一种类似泛型编程语言的性质。

既然我们已经知道mean中还有这么多种类,我们可以输入mean.default试一试就可以得到:

function (x, trim = 0, na.rm = FALSE, ...)

{

if (!is.numeric(x) && !is.complex(x) && !is.logical(x)) {

warning("argument is not numeric or logical: returning NA")

return(as.numeric(NA))

}

if (na.rm)

x <- x[!is.na(x)]

trim <- trim[1]

n <- length(x)

if (trim > 0 && n > 0) {

if (is.complex(x))

stop("trimmed means are not defined for complex data")

if (trim >= 0.5)

return(stats::median(x, na.rm = FALSE))

lo <- floor(n * trim) + 1

hi <- n + 1 - lo

x <- sort.int(x, partial = unique(c(lo, hi)))[lo:hi]

n <- hi - lo + 1

}

.Internal(mean(x))

}

<environment: namespace:base>

同样就可以得到mean.data.frame、mean.Date、mean.difftime、mean.POSIXct、mean.POSIXlt 的具体内容了。值得注意的是,在R中,出现有多个同样近似功能的函数封装为一个函数的时候(这时候在函数中多半会出现类似UseMethod函数使用的情 况),我们不妨先输入mean.default试一试。这种形式的函数在R中一般作为默认的函数表示。

第三,这是一种特殊的情况,有人认为应该和第二种是一类,但是我还是要提出来单独归类。在这种情况也和第二种的原因有些类似,但并不是完全一致。

也许我们大家都很熟悉plot函数了吧,输入函数名plot的时候,我们会得到如下结果:

function (x, y, ...)

{

if (is.null(attr(x, "class")) && is.function(x)) {

nms <- names(list(...))

if (missing(y))

y <- {

if (!"from" %in% nms)

0

else if (!"to" %in% nms)

1

else if (!"xlim" %in% nms)

NULL

}

if ("ylab" %in% nms)

plot.function(x, y, ...)

else plot.function(x, y, ylab = paste(deparse(substitute(x)),

"(x)"), ...)

}

else UseMethod("plot")

}

<environment: namespace:graphics>

请注意plot函数中也出现了UseMethod这个函数,但是和mean不同的是,前面有相当多的语句用于处理其他一些事情。这个时候,我们也使用methods(plot)来看看,得到如下结果:

plot.acf*          plot.data.frame*    plot.Date*          plot.decomposed.ts* plot.default     

plot.dendrogram*    plot.density        plot.ecdf          plot.factor*        plot.formula*   

plot.hclust*        plot.histogram*    plot.HoltWinters*  plot.isoreg*        plot.lm         

plot.medpolish*    plot.mlm            plot.POSIXct*      plot.POSIXlt*      plot.ppr*       

plot.prcomp*        plot.princomp*      plot.profile.nls*  plot.spec          plot.spec.coherency

plot.spec.phase    plot.stepfun        plot.stl*          plot.table*        plot.ts           

plot.tskernel*      plot.TukeyHSD

不看不知道,一看吓一跳,还以为我们输入plot的输出就是函数本身,结果也许不是如此。可能有人已经理解了,其实最后的UseMethod函数实在默认的调用plot.default函数,赶快再看看plot.default函数吧,发现它再调用plot.xy函数,再看看plot.xy函数,再plot.xy函数中调用了一个.Internal(plot.xy(xy, type, pch, lty, col, bg, cex, lwd, ...))函数,也许这就是真正起作用的函数了吧。思路基本上就是如此了,是否这个时候您可以获得一些阅读查找R函数内容的乐趣。

除了直接输入FUN.default形式外,还可以使用getS3method(FUN,"default")来获得代码。这样就解决了绝大多数函数代码查看的工作了。

在第二种情况种,我们说了一般可以通过FUN.default获得想要的结果。但是只有称为generic的函数才有这种“特权”。而lm等则没有,不过我们也可以尝试使用methods(lm)来看看结果如何,发现:

[1] lm.fit      lm.fit.null  lm.influence lm.wfit      lm.wfit.null

Warning message:

function 'lm' appears not to be generic in: methods(lm)

出现了警告信息,表示说lm不是泛型函数,但是还是给出了结果lm.fit等,大致上可以看成是和lm相关的系列函数吧。这样子就出现了有趣的局面,比如说既有plot.ts,也有ts.plot。

依照第三种情况,我们发现竟然有的函数用星号标识了的,比如plot.stl*等,当我们输入plot.stl,甚至是plot.stl*的时候都会给出 要么找不到这个对象,要么干脆是代码错误的信息。原来凡是用了*标识的函数,都是隐藏起来的函数,估计是怕被人看见(其实这是玩笑话)!我们要看这些函数 的代码,我们该怎么办呢?其实也很容易,使用功能强大的getAnywhere(FUN),看看这个函数的名称,就可以猜想到它的功能估计是很强大的, Anywhere的内容都可以找到!getAnywhere(plot.stl)的结果如下:

A single object matching 'plot.stl' was found

It was found in the following places

registered S3 method for plot from namespace stats

namespace:stats

with value

function (x, labels = colnames(X), set.pars = list(mar = c(0,

6, 0, 6), oma = c(6, 0, 4, 0), tck = -0.01, mfrow = c(nplot,

1)), main = NULL, range.bars = TRUE, ..., col.range = "light gray")

{

sers <- x$time.series

ncomp <- ncol(sers)

data <- drop(sers %*% rep(1, ncomp))

X <- cbind(data, sers)

colnames(X) <- c("data", colnames(sers))

nplot <- ncomp + 1

if (range.bars)

mx <- min(apply(rx <- apply(X, 2, range), 2, diff))

if (length(set.pars)) {

oldpar <- do.call("par", as.list(names(set.pars)))

on.exit(par(oldpar))

do.call("par", set.pars)

}

for (i in 1:nplot) {

plot(X[, i], type = if (i < nplot)

"l"

else "h", xlab = "", ylab = "", axes = FALSE, ...)

if (range.bars) {

dx <- 1/64 * diff(ux <- par("usr")[1:2])

y <- mean(rx[, i])

rect(ux[2] - dx, y + mx/2, ux[2] - 0.4 * dx, y -

mx/2, col = col.range, xpd = TRUE)

}

if (i == 1 && !is.null(main))

title(main, line = 2, outer = par("oma")[3] > 0)

if (i == nplot)

abline(h = 0)

box()

right <- i%%2 == 0

axis(2, labels = !right)

axis(4, labels = right)

axis(1, labels = i == nplot)

mtext(labels[i], side = 2, 3)

}

mtext("time", side = 1, line = 3)

invisible()

}

<environment: namespace:stats>

注意到前面有一段解释型的语言,描述了我们要找的这个函数放在了什么地方等等。其实对任意我们可以在R中使用的函数,都可以先试一试getAnywhere,看看都有些什么内容。算是一个比较“霸道”的函数。

在上面plot.xy函数中,我们还可以看到.Internal这个函数,类似的也许还可以看到.Primitive、.External、.Call等函数这就和R系统内部工作方式和与外部接口的定义有关了,如果对这些函数有兴趣的话,就要学习组成R系统的源代码了。

最后,如果真的想阅读组成R系统本身的源代码,在各个CRAN中均有下载。你可以得到组成R系统所需要的材料。其中很多C语言(还有就是F)的源代码,均 是精心挑选过的算法,哪怕就是想学从头到尾编写具体的算法,也是学习的好材料。同时,你可以看到R系统内部是如何构成的,理解了这些对于高效使用R有至关 重要的作用。这个范畴的材料就要着重看一看R-Lang和R-inits了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,686评论 0 3
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,025评论 0 2
  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,435评论 0 13
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,700评论 0 38
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,305评论 0 2