Dr. Alexander Fisher
Duke University
January 25, 2023
value | typeof() |
mode() |
class() |
---|---|---|---|
TRUE |
logical | logical | logical |
1 |
double | numeric | numeric |
1L |
integer | numeric | integer |
"A" |
character | character | character |
NULL |
NULL | NULL | NULL |
list(1, "A") |
list | list | list |
factor("A") |
integer | numeric | factor |
function(x) x^2 |
closure | function | function |
\+ |
builtin | function | function |
\[ |
special | function | function |
objects have class
even if no formal class
attribute (seen with attributes()
)
S3 is R’s core object oriented implementation
S3 is the only OO system used in the base and stats packages, and it’s the most commonly used system in CRAN packages.
S3 is more flexible (read also: easier to break) than traditional object oriented programming you may have seen before (e.g. Java).
Working model: S3 is a system where we attach metadata to an object via the class
attribute.
One of the most compelling reasons to use object oriented programming (OOP) is polymorphism. Polymorphism means that a developer can consider a function’s interface separately from its implementation.
The easiest way to tell if a function is a generic is to use sloop::ftype()
and look for “generic” in the output, e.g.
Fundamentally, the generic function dispatches to a specialized version of the function depending on the class of its input. UseMethod()
tells a generic to look for the specialized version.
The syntax for specialized functions is: <generic>.<class>
We can see all the specialized versions of the generic using the methods()
function.
[1] print.acf*
[2] print.AES*
[3] print.anova*
[4] print.aov*
[5] print.aovlist*
[6] print.ar*
[7] print.Arima*
[8] print.arima0*
[9] print.AsIs
[10] print.aspell*
[11] print.aspell_inspect_context*
[12] print.bibentry*
[13] print.Bibtex*
[14] print.browseVignettes*
[15] print.by
[16] print.changedFiles*
[17] print.check_bogus_return*
[18] print.check_code_usage_in_package*
[19] print.check_compiled_code*
[20] print.check_demo_index*
[21] print.check_depdef*
[22] print.check_details*
[23] print.check_details_changes*
[24] print.check_doi_db*
[25] print.check_dotInternal*
[26] print.check_make_vars*
[27] print.check_nonAPI_calls*
[28] print.check_package_code_assign_to_globalenv*
[29] print.check_package_code_attach*
[30] print.check_package_code_data_into_globalenv*
[31] print.check_package_code_startup_functions*
[32] print.check_package_code_syntax*
[33] print.check_package_code_unload_functions*
[34] print.check_package_compact_datasets*
[35] print.check_package_CRAN_incoming*
[36] print.check_package_datalist*
[37] print.check_package_datasets*
[38] print.check_package_depends*
[39] print.check_package_description*
[40] print.check_package_description_encoding*
[41] print.check_package_license*
[42] print.check_packages_in_dir*
[43] print.check_packages_used*
[44] print.check_po_files*
[45] print.check_pragmas*
[46] print.check_Rd_line_widths*
[47] print.check_Rd_metadata*
[48] print.check_Rd_xrefs*
[49] print.check_RegSym_calls*
[50] print.check_S3_methods_needing_delayed_registration*
[51] print.check_so_symbols*
[52] print.check_T_and_F*
[53] print.check_url_db*
[54] print.check_vignette_index*
[55] print.checkDocFiles*
[56] print.checkDocStyle*
[57] print.checkFF*
[58] print.checkRd*
[59] print.checkRdContents*
[60] print.checkReplaceFuns*
[61] print.checkS3methods*
[62] print.checkTnF*
[63] print.checkVignettes*
[64] print.citation*
[65] print.cli_ansi_html_style*
[66] print.cli_ansi_string*
[67] print.cli_ansi_style*
[68] print.cli_boxx*
[69] print.cli_diff_chr*
[70] print.cli_doc*
[71] print.cli_progress_demo*
[72] print.cli_rule*
[73] print.cli_sitrep*
[74] print.cli_spark*
[75] print.cli_spinner*
[76] print.cli_tree*
[77] print.codoc*
[78] print.codocClasses*
[79] print.codocData*
[80] print.colorConverter*
[81] print.compactPDF*
[82] print.condition
[83] print.connection
[84] print.CRAN_package_reverse_dependencies_and_views*
[85] print.data.frame
[86] print.Date
[87] print.default
[88] print.dendrogram*
[89] print.density*
[90] print.difftime
[91] print.dist*
[92] print.Dlist
[93] print.DLLInfo
[94] print.DLLInfoList
[95] print.DLLRegisteredRoutines
[96] print.document_context*
[97] print.document_position*
[98] print.document_range*
[99] print.document_selection*
[100] print.dummy_coef*
[101] print.dummy_coef_list*
[102] print.ecdf*
[103] print.eigen
[104] print.factanal*
[105] print.factor
[106] print.family*
[107] print.fileSnapshot*
[108] print.findLineNumResult*
[109] print.formula*
[110] print.fseq*
[111] print.ftable*
[112] print.function
[113] print.getAnywhere*
[114] print.glm*
[115] print.hclust*
[116] print.help_files_with_topic*
[117] print.hexmode
[118] print.HoltWinters*
[119] print.hsearch*
[120] print.hsearch_db*
[121] print.htest*
[122] print.html*
[123] print.html_dependency*
[124] print.htmltools.selector*
[125] print.htmltools.selector.list*
[126] print.infl*
[127] print.integrate*
[128] print.isoreg*
[129] print.json*
[130] print.key_missing*
[131] print.kmeans*
[132] print.knitr_kable*
[133] print.Latex*
[134] print.LaTeX*
[135] print.libraryIQR
[136] print.listof
[137] print.lm*
[138] print.loadings*
[139] print.loess*
[140] print.logLik*
[141] print.ls_str*
[142] print.medpolish*
[143] print.method_table*
[144] print.MethodsFunction*
[145] print.mtable*
[146] print.NativeRoutineList
[147] print.news_db*
[148] print.nls*
[149] print.noquote
[150] print.numeric_version
[151] print.object_size*
[152] print.octmode
[153] print.packageDescription*
[154] print.packageInfo
[155] print.packageIQR*
[156] print.packageStatus*
[157] print.pairwise.htest*
[158] print.person*
[159] print.POSIXct
[160] print.POSIXlt
[161] print.power.htest*
[162] print.ppr*
[163] print.prcomp*
[164] print.princomp*
[165] print.proc_time
[166] print.quosure*
[167] print.quosures*
[168] print.raster*
[169] print.Rd*
[170] print.recordedplot*
[171] print.restart
[172] print.RGBcolorConverter*
[173] print.rlang_box_done*
[174] print.rlang_box_splice*
[175] print.rlang_data_pronoun*
[176] print.rlang_dict*
[177] print.rlang_dyn_array*
[178] print.rlang_envs*
[179] print.rlang_error*
[180] print.rlang_fake_data_pronoun*
[181] print.rlang_lambda_function*
[182] print.rlang_message*
[183] print.rlang_trace*
[184] print.rlang_warning*
[185] print.rlang_zap*
[186] print.rlang:::list_of_conditions*
[187] print.rle
[188] print.rlib_bytes*
[189] print.rlib_error_3_0*
[190] print.rlib_trace_3_0*
[191] print.roman*
[192] print.scalar*
[193] print.sessionInfo*
[194] print.shiny.tag*
[195] print.shiny.tag.env*
[196] print.shiny.tag.list*
[197] print.shiny.tag.query*
[198] print.simple.list
[199] print.smooth.spline*
[200] print.socket*
[201] print.srcfile
[202] print.srcref
[203] print.stepfun*
[204] print.stl*
[205] print.StructTS*
[206] print.subdir_tests*
[207] print.summarize_CRAN_check_status*
[208] print.summary.aov*
[209] print.summary.aovlist*
[210] print.summary.ecdf*
[211] print.summary.glm*
[212] print.summary.lm*
[213] print.summary.loess*
[214] print.summary.manova*
[215] print.summary.nls*
[216] print.summary.packageStatus*
[217] print.summary.ppr*
[218] print.summary.prcomp*
[219] print.summary.princomp*
[220] print.summary.table
[221] print.summary.warnings
[222] print.summaryDefault
[223] print.table
[224] print.tables_aov*
[225] print.terms*
[226] print.ts*
[227] print.tskernel*
[228] print.TukeyHSD*
[229] print.tukeyline*
[230] print.tukeysmooth*
[231] print.undoc*
[232] print.vignette*
[233] print.warnings
[234] print.xfun_raw_string*
[235] print.xfun_rename_seq*
[236] print.xfun_strict_list*
[237] print.xgettext*
[238] print.xngettext*
[239] print.xtabs*
see '?methods' for accessing help and source code
Write the name of the function to see its definition.
function (x, quote = FALSE, max.levels = NULL, width = getOption("width"),
...)
{
ord <- is.ordered(x)
if (length(x) == 0L)
cat(if (ord)
"ordered"
else "factor", "(0)\n", sep = "")
else {
xx <- character(length(x))
xx[] <- as.character(x)
keepAttrs <- setdiff(names(attributes(x)), c("levels",
"class"))
attributes(xx)[keepAttrs] <- attributes(x)[keepAttrs]
print(xx, quote = quote, ...)
}
maxl <- if (is.null(max.levels))
TRUE
else max.levels
if (maxl) {
n <- length(lev <- encodeString(levels(x), quote = ifelse(quote,
"\"", "")))
colsep <- if (ord)
" < "
else " "
T0 <- "Levels: "
if (is.logical(maxl))
maxl <- {
width <- width - (nchar(T0, "w") + 3L + 1L +
3L)
lenl <- cumsum(nchar(lev, "w") + nchar(colsep,
"w"))
if (n <= 1L || lenl[n] <= width)
n
else max(1L, which.max(lenl > width) - 1L)
}
drop <- n > maxl
cat(if (drop)
paste(format(n), ""), T0, paste(if (drop)
c(lev[1L:max(1, maxl - 1)], "...", if (maxl > 1) lev[n])
else lev, collapse = colsep), "\n", sep = "")
}
if (!isTRUE(val <- .valid.factor(x)))
warning(val)
invisible(x)
}
<bytecode: 0x7fa01974f030>
<environment: namespace:base>
There is no method to print integers specifically:
function (x, digits = NULL, quote = TRUE, na.print = NULL, print.gap = NULL,
right = FALSE, max = NULL, width = NULL, useSource = TRUE,
...)
{
args <- pairlist(digits = digits, quote = quote, na.print = na.print,
print.gap = print.gap, right = right, max = max, width = width,
useSource = useSource, ...)
missings <- c(missing(digits), missing(quote), missing(na.print),
missing(print.gap), missing(right), missing(max), missing(width),
missing(useSource))
.Internal(print.default(x, args, missings))
}
<bytecode: 0x7fa01a9c3f50>
<environment: namespace:base>
[1] [ [[ [[<- [<- all.equal
[6] as.character as.data.frame as.Date as.list as.logical
[11] as.POSIXlt as.vector c coerce droplevels
[16] format initialize is.na<- length<- levels<-
[21] Math Ops plot print relevel
[26] relist rep show slotsFromS3 summary
[31] Summary xtfrm
see '?methods' for accessing help and source code
cloud = structure(c(1, 2, 3), # object called cloud with some values
class = "first_class") # new class type
cloud
[1] 1 2 3
attr(,"class")
[1] "first_class"
first_class
objectsCreate a class called “accounting”. If a numeric vector has this class, function print()
should print the vector with a $ in front of each number and display values up to two decimals. Create a method for this class and test it on the accounting object expenses
below
Below is an S3 method called report
, it is designed to return a message about the type/mode/class of an object passed to it.
Create an implementation for classes integer
, double
and numeric
. The functions should print to the screen “I’m an integer”, “I’m a double”, and “I’m a numeric” respectively.
Next,
report(1)
and report(1L)
.rm("report.integer")
and re-run the functions. What has changed?class(1)
, mode(1)
, typeof(1)
. Does this surprise you?class
searching rule.Date
classDate vectors are built on top of double vectors. They have class “Date” and no other attributes:
The date is measured in unix time, that is, the number of days that have passed since January 1st, 1970. Seconds are counted similarly, startin from the beginning of time, 1970 00:00:00 UTC
.
R offers two ways to store date-time info. POSIXct
, and POSIXlt
POSIX stands for “Portable Operating Systems Interface” X (“across”) platforms
ct
: calendar timelt
: local timect
is the simplest, is built on top of an atomic vector, and is most appropriate for use in data frames.
today
?today
?difftime
R supports the creation of 2d data structures (rows and columns) of atomic vector types. Generally these are formed via a call to matrix().
Matrices (and arrays) are just atomic vectors with a dim attribute attached (they do not have a class attribute, but they do have a class).
Arrays are just an \(n\)-dimensional extension of matrices and are defined by adding the appropriate dimension sizes.
Data frames are built on top of lists with attributes: names, row.names, and class. Here the class is data.frame
.
[1] "list"
$names
[1] "speed" "dist"
$class
[1] "data.frame"
$row.names
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
[26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
List of 2
$ speed: num [1:50] 4 4 7 7 8 9 10 10 10 11 ...
$ dist : num [1:50] 2 10 4 22 16 10 18 26 34 17 ...
- attr(*, "row.names")= int [1:50] 1 2 3 4 5 6 7 8 9 10 ...
A data frame is how R handles heterogeneous tabular data (i.e. rows and columns) and is one of the most commonly used data structure in R.