17.2 Code
We can actually see the contents of a function by typing sd
(with no ?
and no parentheses). Sometimes we will see the function explicitly written out. Here is the code for sd
.
function (x, na.rm = FALSE)
sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x),
na.rm = na.rm))
<bytecode: 0x55e4e24b9410>
<environment: namespace:stats>
The code for sd
finds the square root of the variance of x
.
17.2.1 Generic functions
If we try to look at the code for print
, we’ll see this.
standardGeneric for "print" defined from package "base"
function (x, ...)
standardGeneric("print")
<environment: 0x55e4e2117780>
Methods may be defined for arguments: x
Use showMethods(print) for currently available ones.
All we see here is UseMethod("print")
because print
is a generic function that will use different code depending on whether we give it a data.frame
, list
or some other object. For example, if we give print
a list
, it will show each object in the list, each labeled with $nameoftheobject
and separated by a blank line.
Code
[1] "list" "vector"
$x1
[1] 1 2 3 4 5 6 7 8 9 10
$x2
[1] 11 12 13 14 15 16 17 18 19 20
$x3
[1] 21 22 23 24 25 26 27 28 29 30
$x4
[1] 31 32 33 34 35 36 37 38 39 40
$x5
[1] 41 42 43 44 45 46 47 48 49 50
$x6
[1] 51 52 53 54 55 56 57 58 59 60
$x7
[1] 61 62 63 64 65 66 67 68 69 70
If this list
were a data.frame
object, it would show a table of data.
[1] "data.frame" "list" "oldClass" "vector"
x1 x2 x3 x4 x5 x6 x7
1 1 11 21 31 41 51 61
2 2 12 22 32 42 52 62
3 3 13 23 33 43 53 63
4 4 14 24 34 44 54 64
5 5 15 25 35 45 55 65
6 6 16 26 36 46 56 66
7 7 17 27 37 47 57 67
8 8 18 28 38 48 58 68
9 9 19 29 39 49 59 69
10 10 20 30 40 50 60 70
If we have an lm
object that is the result of fitting a linear regression to data using the function lm
, print
shows some basic information about the model.
[1] "lm" "oldClass"
Call:
lm(formula = mpg ~ wt, data = mtcars)
Coefficients:
(Intercept) wt
37.285 -5.344
If we have a summary.lm
object, print
will give an output with coefficients, standard errors, t-statistics, p-values, the significance stars, \(R^2\), Adjusted \(R^2\), and so on
[1] "summary.lm"
Call:
lm(formula = mpg ~ wt, data = mtcars)
Residuals:
Min 1Q Median 3Q Max
-4.5432 -2.3647 -0.1252 1.4096 6.8727
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 37.2851 1.8776 19.858 < 2e-16 ***
wt -5.3445 0.5591 -9.559 1.29e-10 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 3.046 on 30 degrees of freedom
Multiple R-squared: 0.7528, Adjusted R-squared: 0.7446
F-statistic: 91.38 on 1 and 30 DF, p-value: 1.294e-10
17.2.2 methods
We can use methods
to see what objects the function print
has methods for.
[1] "print,ANY-method" "print,bayesglm-method"
[3] "print,bayespolr-method" "print,diagonalMatrix-method"
[5] "print,ggmultiplot-method" "print,sparseMatrix-method"
[7] "print.aareg" "print.abbrev"
[9] "print.acf" "print.activeConcordance"
[11] "print.ada" "print.AES"
[13] "print.all_vars" "print.allFit"
[15] "print.anova" "print.Anova"
[17] "print.anova.gam" "print.anova.lme"
[19] "print.anova.loglm" "print.any_vars"
We are using head
(also generic!) to only show the first 20 methods. There are actually several hundred!
[1] 854
Here are the methods that contain the character string lm
as part of the name.
[1] "print,bayesglm-method" "print.anova.lme" "print.anova.loglm"
[4] "print.gelman.diag" "print.glm" "print.glm.dose"
[7] "print.intervals.lme" "print.intervals.lmList" "print.lm"
[10] "print.lme" "print.lmList" "print.loglm"
[13] "print.ranef.lme" "print.ridgelm" "print.rlm"
[16] "print.simulate.lme" "print.summary.glm" "print.summary.lm"
[19] "print.summary.lme" "print.summary.lmList" "print.summary.loglm"
[22] "print.summary.rlm" "print.VarCorr.lme"
17.2.3 getAnywhere
If we want to see the code for one of these methods, we can use getAnywhere
. Let’s see the code for print.lm
and print.summary.lm
. Since the output of print(summary.lm)
above is much more detailed than print(lm1)
, it is not surprising that the code for print.summary.lm
is much more involved than the code for print.lm
.
A single object matching 'print.lm' was found
It was found in the following places
registered S3 method for print from namespace stats
namespace:stats
with value
function (x, digits = max(3L, getOption("digits") - 3L), ...)
{
cat("\nCall:\n", paste(deparse(x$call), sep = "\n", collapse = "\n"),
"\n\n", sep = "")
if (length(coef(x))) {
cat("Coefficients:\n")
print.default(format(coef(x), digits = digits), print.gap = 2L,
quote = FALSE)
}
else cat("No coefficients\n")
cat("\n")
invisible(x)
}
<bytecode: 0x55e4ecb638d8>
<environment: namespace:stats>
A single object matching 'print.summary.lm' was found
It was found in the following places
registered S3 method for print from namespace stats
namespace:stats
with value
function (x, digits = max(3L, getOption("digits") - 3L), symbolic.cor = x$symbolic.cor,
signif.stars = getOption("show.signif.stars"), ...)
{
cat("\nCall:\n", paste(deparse(x$call), sep = "\n", collapse = "\n"),
"\n\n", sep = "")
resid <- x$residuals
df <- x$df
rdf <- df[2L]
cat(if (!is.null(x$weights) && diff(range(x$weights)))
"Weighted ", "Residuals:\n", sep = "")
if (rdf > 5L) {
nam <- c("Min", "1Q", "Median", "3Q", "Max")
rq <- if (length(dim(resid)) == 2L)
structure(apply(t(resid), 1L, quantile), dimnames = list(nam,
dimnames(resid)[[2L]]))
else {
zz <- zapsmall(quantile(resid), digits + 1L)
structure(zz, names = nam)
}
print(rq, digits = digits, ...)
}
else if (rdf > 0L) {
print(resid, digits = digits, ...)
}
else {
cat("ALL", df[1L], "residuals are 0: no residual degrees of freedom!")
cat("\n")
}
if (length(x$aliased) == 0L) {
cat("\nNo Coefficients\n")
}
else {
if (nsingular <- df[3L] - df[1L])
cat("\nCoefficients: (", nsingular, " not defined because of singularities)\n",
sep = "")
else cat("\nCoefficients:\n")
coefs <- x$coefficients
if (any(aliased <- x$aliased)) {
cn <- names(aliased)
coefs <- matrix(NA, length(aliased), 4, dimnames = list(cn,
colnames(coefs)))
coefs[!aliased, ] <- x$coefficients
}
printCoefmat(coefs, digits = digits, signif.stars = signif.stars,
na.print = "NA", ...)
}
cat("\nResidual standard error:", format(signif(x$sigma,
digits)), "on", rdf, "degrees of freedom")
cat("\n")
if (nzchar(mess <- naprint(x$na.action)))
cat(" (", mess, ")\n", sep = "")
if (!is.null(x$fstatistic)) {
cat("Multiple R-squared: ", formatC(x$r.squared, digits = digits))
cat(",\tAdjusted R-squared: ", formatC(x$adj.r.squared,
digits = digits), "\nF-statistic:", formatC(x$fstatistic[1L],
digits = digits), "on", x$fstatistic[2L], "and",
x$fstatistic[3L], "DF, p-value:", format.pval(pf(x$fstatistic[1L],
x$fstatistic[2L], x$fstatistic[3L], lower.tail = FALSE),
digits = digits))
cat("\n")
}
correl <- x$correlation
if (!is.null(correl)) {
p <- NCOL(correl)
if (p > 1L) {
cat("\nCorrelation of Coefficients:\n")
if (is.logical(symbolic.cor) && symbolic.cor) {
print(symnum(correl, abbr.colnames = NULL))
}
else {
correl <- format(round(correl, 2), nsmall = 2,
digits = digits)
correl[!lower.tri(correl)] <- ""
print(correl[-1, -p, drop = FALSE], quote = FALSE)
}
}
}
cat("\n")
invisible(x)
}
<bytecode: 0x55e4dce10870>
<environment: namespace:stats>
17.2.4 Other resources
This Stack Overflow answer is pretty useful and has more details. https://stackoverflow.com/questions/19226816/how-can-i-view-the-source-code-for-a-function
More in R for Data science: https://r4ds.had.co.nz/vectors.html?q=methods#attributes
More in Advanced R: http://adv-r.had.co.nz/OO-essentials.html#s3