Author
Published

April 7, 2025

You probably engaged in endless debates about {tidyverse} versus {base} R and/or {data.table}.1 But what does “base R” actually mean? Clarifying this may unite the dichotomy (or trichotomy), that we are all R. But, wait, we’re all R? What about “R or Python”? Oh no, don’t let the holy war escalate! Again, we’re all one . . . embrace both like me, like RStudio . . . in fact, become a polyglot.

Back to base R, it is typically used to refer to the set of packages that come or distributed with R2. The name “base” might be confusing, because of {base}, the fundamental package that “contains the basic functions which let R function as a language”. However, base R encompasses more than {base}. Pause and count how many base R packages you can name. . . .

Code
lib_path = normalizePath(.Library)
# [1] "/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library"
fields = c("Title")

installed_pkgs = installed.packages(lib_path, fields=fields) |> as.data.frame()

base_pkgs = subset(installed_pkgs, Priority == "base", select =  c("Package", fields))
high_pkgs = subset(installed_pkgs, Priority == "high", select = c("Package", fields))

There are 14 base R packages, in R 4.4.3. Below is a complete list.

Base R Packages
Code
sprintf("- %s --- %s", base_pkgs$Package, base_pkgs$Title) |>
cat(sep = "\n")
  • base — The R Base Package
  • compiler — The R Compiler Package
  • datasets — The R Datasets Package
  • graphics — The R Graphics Package
  • grDevices — The R Graphics Devices and Support for Colours and Fonts
  • grid — The Grid Graphics Package
  • methods — Formal Methods and Classes
  • parallel — Support for Parallel Computation in R
  • splines — Regression Spline Functions and Classes
  • stats — The R Stats Package
  • stats4 — Statistical Functions using S4 Classes
  • tcltk — Tcl/Tk Interface
  • tools — Tools for Package Development
  • utils — The R Utils Package

See ?installed.packages.

Some of these packages I did not know exist, let alone knowingly use. So the list shows that base R includes packages attached to your R session by default (i.e. default packages), and other few important packages used behind the scenes. Therefore, in short, base R = {{base}, {default}, {other}} packages.

Code
default_pkgs = in_plain_r("cat(getOption('defaultPackages'))")
default_pkgs = strsplit(default_pkgs, " ")[[1]]

The default packages are attached when R starts up. As of R 4.4.3 these are: {datasets}, {utils}, {grDevices}, {graphics}, {stats}, and {methods}. Obviously, add {base} to the list. You can also see them in the search path (prepended with package:):

Code
in_plain_r("cat(search())")
[1] ".GlobalEnv package:stats package:graphics package:grDevices package:utils package:datasets package:methods Autoloads package:base"

You can control the list of default packages by setting the environment variable R_DEFAULT_PACKAGES with a comma-separated list of packages. You may ask, why do we need to do that? Well:

Changing the set of default packages is normally used to reduce the set for speed when scripting: in particular not using methods will reduce the start-up time by a factor of up to two. But it can also be used to customize R, e.g. for class use. Rscript also checks the environment variable R_SCRIPT_DEFAULT_PACKAGES; if set, this takes precedence over R_DEFAULT_PACKAGES.

R manuals #Default-packages

Tip

To modify the list of default packages, set the env variable R_DEFAULT_PACKAGES in your .Renviron, or set the defaultPackages option in .Rprofile (see R manuals). If you set R_DEFAULT_PACKAGES=NULL, then only {base} is loaded.

# ~/.Renviron
R_DEFAULT_PACKAGES=base,utils,stats,methods

Or,

# ~/.Rprofile
options(defaultPackages=c("base", "utils", "stats", "methods"))

As you can see below, only {base} is loaded when no default packages are provided.

Code
system('export R_DEFAULT_PACKAGES=NULL;R --vanilla --no-echo --quiet -e "cat(search())"', intern=TRUE)
[1] ".GlobalEnv Autoloads package:base"
Code
other_base_pkgs = setdiff(base_pkgs$Package, c("base", default_pkgs))

The other base R packages are {compiler}, {grid}, {parallel}, {splines}, {stats4}, {tcltk}, and {tools}. These (or some) may not be familiar to you (myself included) if you’re not a package developer. I have used {tools} for example to check package dependencies (e.g., tools::package_dependencies("data.table", recursive = TRUE)), and work with file paths (see my tweet). I have also lightly used {grid} to add annotations to base plots. Have you ever used {tcltk}?

In sum, when people say “I use base R”, they probably mean {base} functions because the comparison is mostly about data manipulation/wrangling, not say visualization (base {graphics} vs {ggplot2}) or other tasks.3 Not true? See examples here, here. In other words, if you use df[df$x > 1, ] instead of say dplyr::filter(df, x > 1), or data.table::as.data.table(df)[x > 1, ], you’re a base R-er. However, base R “should” refer to the suite of built-in packages in R (14 as of R 4.4.3), like {tidyverse} which is a collection of diverse (but related) packages from everyday data analyses to specialized packages.

Footnotes

  1. If you want to read some, see here, here, here, “a poem about the battle”, and many more in the bird site. Sorry for the X links. Most of the debates occurred during the #rstats Twitter era.↩︎

  2. Packages that come built-in with R may include more than base R packages: installed.packages(priority="high") shows base + recommended packages.↩︎

  3. Most, if not all, base R-ers use {ggplot2}, lovingly.↩︎

Citation

BibTeX citation:
@online{beze2025,
  author = {Beze, Eyayaw},
  title = {Base {R}},
  date = {2025-04-07},
  url = {https://eyayaw.github.io/posts/base-r.html},
  langid = {en}
}
For attribution, please cite this work as:
Beze, Eyayaw. 2025. “Base R.” April 7, 2025. https://eyayaw.github.io/posts/base-r.html.