What R is
R is a language made for statistics and data analysis, in which the basic unit is a vector of values rather than a single value, so arithmetic, comparisons and summaries apply to a whole column at once. Writing it feels less like building an application and more like questioning a dataset: load it, try a function in the console, look at the result, refine. It is free and open source, and it grows through packages on CRAN, the same network that distributes R itself.
Where R is used
- Statistical analysis
- Linear models, t-tests, ANOVA and probability distributions are part of base R, so a standard analysis needs no extra packages.
- Data cleaning and exploration
- Data frames, R's tables, are built into the language, and the dplyr and tidyr packages add readable verbs for filtering, grouping and reshaping them.
- Charts and figures
- ggplot2 builds a chart from layers, mapping columns to position, colour and size, with fine control over figures for reports and papers.
- Bioinformatics and research
- The Bioconductor project distributes R packages for analysing genomic and other biological data.
- Interactive dashboards
- Shiny turns R code into a web app with inputs, tables and charts, without the author writing HTML or JavaScript.
Your first R program
Saved as scores.R. You can paste it straight into the playground to see it run.
scores <- c(72, 85, 90, 64)
average <- mean(scores)
cat("Average score: ", average, "\n", sep = "")
print(scores + 5)
print(scores[scores > average])What it prints
Average score: 77.75
[1] 77 90 95 69
[1] 85 90- Line 1 builds a vector with
c(), short for combine: four numbers, in order.<-is the assignment arrow;=also works, but most R code uses the arrow. - Line 2 passes the whole vector to
mean(), which returns 77.75. No loop is needed, because R functions are built to work on a set of values at once. - Line 4 prints with
cat(), which puts a space between its arguments unlesssep = ""says otherwise, and never ends a line by itself, which is why"\n"is passed last. - Line 5 adds 5 to every element and prints the result with
print(). The[1]is not part of the data: R labels each printed line with the position of its first element. - Line 6 compares every score with the average, giving TRUE or FALSE for each, and the square brackets keep only the elements where the answer is TRUE: 85 and 90.
Run R on your own computer
R is a free download from CRAN. The installer gives you the language, a basic console and the Rscript command for running files; an editor is optional and installed separately.
Install R from CRAN
At cran.r-project.org, choose your operating system. On Windows, run the base installer. On macOS, pick the arm64 package for Apple silicon or the x86_64 package for Intel Macs. On Linux, install r-base on Debian and Ubuntu, or R on Fedora.
Check Rscript works
On macOS and Linux this usually works straight away. The Windows installer does not add R to PATH, so add the bin folder under C:\Program Files\R to PATH, or type the full path to Rscript.exe.
ShellRscript --versionSave the file and run it
Save the first program as scores.R and run it from the folder it is in. Rscript shows what the script prints without echoing the code. For trying single lines, the R app the installer adds opens an interactive console.
ShellRscript scores.RAdd packages and, if you like, an editor
Install a package once from inside R with install.packages("ggplot2"), then load it in each script with library(ggplot2). Any text editor can write R. RStudio and Positron, both free from Posit, put a console, plots and a data viewer beside the editor; both need R installed first.
A learning order for R
Stages, not a timetable. Each one exists because the next would not make sense without it, and how long each takes depends on how much you write.
Stage 1. Values and vectors
- assignment with <-
- numbers, text and TRUE/FALSE
- c() and arithmetic on vectors
- indexing from 1
- print() and cat()
Vectors are what the rest of R is built on. Once a column, a result and even a single number all read as vectors, much of the language stops being surprising.
Stage 2. Functions and control flow
- named arguments
- help pages with ?mean
- writing function()
- if and else
- for loops versus vectorised functions
R's functions take many optional arguments, and the help pages are how you find them. Much R code replaces loops with functions that act on a whole vector, so it helps to see both early.
Stage 3. Data frames and real data
- data frames and the $ operator
- read.csv()
- choosing rows and columns with [row, column]
- NA and na.rm
- the working directory
Nearly every analysis works on a data frame, a table whose columns are vectors. Missing values and file paths cause a lot of early frustration, so they belong here rather than later.
Stage 4. Packages and the tidyverse
- install.packages() and library()
- dplyr: filter, mutate, group_by, summarise
- the pipe, |> or %>%
- tidyr and readr
The tidyverse packages share a consistent style for cleaning data, and a lot of current R material uses them. Coming to them after base R means you know what they do underneath.
Stage 5. Charts and statistics
- ggplot2 and its layers
- plot() and hist()
- summary() and table()
- t.test() and cor()
- lm() and reading its output
This is the work R was made for. Plotting before modelling is a sensible order, because a chart often reveals a problem in the data that a model summary would hide.
Stage 6. Reproducible work
- Quarto or R Markdown documents
- projects and relative paths
- renv for package versions
- Shiny apps
An analysis is only trustworthy when someone else can rerun it. Documents that mix code with results, and projects that record their package versions, make that possible.
Mistakes beginners make in R
- Getting NA back from mean() or sum()
- One missing value, NA, makes most summary functions return NA, because R will not guess what it was. Use mean(x, na.rm = TRUE). For the same reason, x == NA never finds missing values, since comparing with an unknown gives an unknown. Use is.na(x) instead.
- Counting from 0
- R numbers positions from 1. x[0] is not an error but an empty vector, and a position past the end gives NA, so both mistakes can travel a long way through a script before anything looks wrong.
- Reading a file from the wrong folder
- read.csv("data.csv") looks in the working directory, which is wherever R was started, not where the script is saved. An error saying cannot open the connection means the path is wrong, not the file. Check with getwd(), and run scripts from their own folder or inside an RStudio or Positron project.
- Calling library() for a package that is not installed
- library() only loads packages already on your computer; otherwise R stops and says there is no package by that name. Run install.packages("dplyr") once, then library(dplyr) in each script. Leaving install.packages() in a script downloads the package again on every run.
- Writing x<-5 when you meant x < -5
- Without spaces, <- is the assignment arrow, so if (x<-5) quietly sets x to 5 and counts as true, instead of checking whether x is below minus five. There is no warning. Spaces around operators prevent it.
Strengths and trade-offs
Where it is strong
- Statistics is built in: regression, hypothesis tests and distributions need nothing extra installed.
- Strong charting, especially with ggplot2, which gives precise control over every part of a figure.
- Specialised packages on CRAN and Bioconductor, often written by the statisticians who developed the methods.
- Quarto and R Markdown reports combine code, output and text, so an analysis can be rerun rather than copied and pasted.
Where it is not
- Inconsistent in places: names mix styles (read.csv, readRDS, nchar), there are several object systems, and base R and the tidyverse solve the same problems differently, so tutorials often disagree.
- Error messages can be cryptic. object of type 'closure' is not subsettable usually means a function name such as data or df was used as if it were your own variable.
- Data normally has to fit in memory, and plain loops are slow; large datasets call for data.table, arrow or a database.
- Not a general-purpose language: a poor fit for web backends, apps or command-line tools, and deep-learning tooling is mostly Python-first.
Who R is for
R is a good first language for people whose work is data: students and researchers in statistics, biology, psychology, economics or public health, and analysts who have outgrown spreadsheets. It gets you to a summary table or a clear chart with very little general programming knowledge. If your goal is software development in general, websites, apps or machine-learning engineering, start with Python or JavaScript instead; R is easy to add later if statistics becomes part of your work.
Questions about learning R
- Should I learn R or Python for data analysis?
- It depends on where you are heading. R is stronger for classical statistics, specialised research methods, and quick charts and reports; Python is stronger when the analysis has to become part of a larger program, and for machine learning. Use whatever your course, lab or team uses, because that matters more than the differences. Learning one makes the other easier.
- Do I need RStudio to use R?
- No. R runs on its own, through its console or Rscript, and any text editor can write R code. RStudio and Positron are separate editors that use the R you installed from CRAN, so if one of them is not working, first check that R itself starts.
- Should I learn base R or the tidyverse first?
- Learn enough base R to understand vectors, indexing, data frames and NA, because the tidyverse is built on them and its error messages mention them. After that, dplyr and ggplot2 are a sensible next step. The two styles mix freely in one script, so you are not locked into either.
- Why does R print [1] before my results?
- It is a position label, not part of the value. Each printed line of a vector starts with the index of its first element in square brackets, so a long vector that wraps shows other numbers at the start of later lines. cat() prints values without these labels.
The primary source
When this guide and the official documentation disagree, the documentation is right and we would like to hear about it.