What a Package Is
A package is a bundle of functions, documentation, and sometimes data that extends R. Base R gives you vectors, models, and plots; packages give you everything else - and the "everything else" is enormous. CRAN (the Comprehensive R Archive Network) hosts roughly 20,000 packages, every one of them checked against CRAN's submission tests before it's published. That repository is the main reason R stays competitive for data work: whatever the analysis, someone has probably packaged it.
CRAN isn't the only source - Bioconductor hosts the bioinformatics ecosystem, and plenty of in-development packages live on GitHub (installable with remotes::install_github()) - but as a beginner you can treat CRAN as the default and the others as things you'll meet when a README tells you to.
A handful of packages ship with R itself (stats, utils, graphics, and friends) and load automatically - that's why mean() and plot() just work. Everything else follows the two-step ritual below.
install.packages() Once, library() Every Session
This is the #1 beginner confusion, so here it is as crisply as possible. Getting a package working is two different actions with two different lifetimes:
install.packages("dplyr") # ONCE per machine: downloads from CRAN and installs
library(dplyr) # EVERY session: loads it so your code can use it
install.packages("dplyr")is like buying a book: you do it once, and it sits on your shelf (your disk) from then on. Note the quotes - you're passing the name as a string.library(dplyr)is like taking the book off the shelf: you do it at the start of every R session (in practice, at the top of every script). No quotes needed here -library()is special and accepts the bare name (library("dplyr")also works, if you prefer consistency).
The two failure modes tell you which step you skipped. Error: there is no package called 'dplyr' from library() means it was never installed. Error: could not find function "filter" (or "%>%") halfway through a script means the package is installed but this session never loaded it. Putting every library() call at the very top of the script - not scattered through it - makes the second failure visible in the first second, and doubles as a list of the script's dependencies. Installing tidyverse works the same way: install.packages("tidyverse") once, library(tidyverse) per session, which loads dplyr, ggplot2, and the rest of the core set in one line.
What you should not do is leave install.packages() inside a script you run repeatedly or share - it re-downloads on every run and may surprise whoever executes it. Installation is a console act; loading is a script act.
require() and pkg::fun()
require() looks like a synonym for library(), and misusing it as one is common. The difference is what happens when the package is missing: library() stops with an error; require() prints a warning, returns FALSE, and lets the script continue - usually to die twenty lines later with a confusing "could not find function" instead of the honest "no package called" message. For loading dependencies, use library(): failing loudly at the top is a feature. require() earns its keep only in conditional checks, where its return value is the point:
if (!require(praise)) {
install.packages("praise")
library(praise)
}
There's also a way to use a package without loading it at all: the :: operator calls one function by its full address, package::function(). The package must be installed, but nothing is attached to your session:
(stats is auto-loaded anyway, so plain sd() works too - but the syntax is the same for any installed package.) :: shines in two places: one-off calls where a full library() line is overkill, and disambiguation when two loaded packages export the same name - dplyr::filter() vs stats::filter() is the classic collision.
Keeping Packages Up to Date
Packages evolve independently of R, so updating is on you:
update.packages() # offers to update everything outdated
update.packages(ask = FALSE) # same, without prompting per package
One non-obvious rule: packages are built against a specific major.minor version of R. When you upgrade R itself (say 4.3 to 4.4 - see installing R), your old package library is generally not carried over, and the fix is simply to reinstall the packages you use under the new version. Ten minutes of install.packages(), not a disaster - but it surprises people the first time their scripts greet a fresh R install with a wall of "no package called" errors.
Seeing What You Have
Three functions answer "what's installed and where":
installed.packages()[, "Version"] # every installed package with its version
sessionInfo() # R version + what THIS session has loaded
.libPaths() # the folders where packages are installed
installed.packages() returns a matrix with one row per package - the Version column is usually what you want. sessionInfo() is the reproducibility tool: paste its output into a bug report and the reader knows your R version, OS, and the exact versions of every loaded package. .libPaths() shows the library folders R searches; knowing it exists demystifies "where did that package actually go?" and why admin rights sometimes matter on shared machines.
Packages Worth Knowing
You don't need these today, but you'll meet them constantly - knowing what each is for helps you read other people's code:
- dplyr - the data-manipulation verbs:
filter,mutate,group_by,summarize. - ggplot2 - the standard plotting package; most R graphics you see online are ggplot2.
- tidyr - reshaping data between wide and long forms (
pivot_longer,pivot_wider). - readr / readxl - fast CSV reading and Excel file reading respectively.
- lubridate - dates that behave the way you expect.
- stringr - consistent string manipulation.
- data.table - an alternative high-performance data-frame ecosystem; a different dialect from the tidyverse, beloved for big data.
- shiny - interactive web apps written entirely in R.
The first six are the core of the tidyverse and arrive together with install.packages("tidyverse"). There is no obligation to use any of them - base R can do all of it - but the ecosystem is where most modern R code lives.
What You Take Away
- CRAN hosts ~20,000 vetted packages; Bioconductor and GitHub cover the rest.
install.packages("name")once per machine (quotes required);library(name)once per session, at the top of the script.library()fails loudly - good;require()returnsFALSE- only useful inside checks.pkg::fun()uses one function without attaching the package, and resolves name collisions.update.packages()keeps things current; a major R upgrade means reinstalling packages.sessionInfo()is how you tell someone (or future you) exactly what your code ran on.
Next up: the working directory - where R looks for files, and why that's the first thing to check when reading data fails.
Frequently Asked Questions
How do I install a package in R?
Run install.packages("name") with the package name in quotes, e.g. install.packages("dplyr"). R downloads it from CRAN and installs it on your machine. You only do this once per machine - after that, load it in each session with library(dplyr).
What is the difference between install.packages() and library()?
install.packages("dplyr") downloads the package onto your computer - once per machine. library(dplyr) loads an already-installed package into the current session - once per session, typically at the top of every script. Installing without loading gives you nothing usable; loading without installing errors with "there is no package called 'dplyr'".
What is the difference between library() and require() in R?
Both load a package, but on failure library() stops with an error while require() just warns and returns FALSE. That makes library() right for scripts - fail loudly and early - and require() only useful inside conditional checks like if (!require(pkg)) install.packages(pkg).