當前位置:編程學習大全網 - 源碼下載 - r語言中怎樣查看函數源代碼

r語言中怎樣查看函數源代碼

在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了。

至此,R中閱讀代碼的內容就依照我的理解介紹了壹下。隨後將有壹些R代碼示例的分析註解、語言本身、R應用的和行業使用的材料翻譯和具體例子說明。歡迎大家多多和我交流,壹起進步。

  • 上一篇:Dubbo——HTTP 協議 + JSON-RPC
  • 下一篇:jdk1.6.0_14如何編譯和運行
  • copyright 2024編程學習大全網