4  Getting Started with R

This chapter covers why we are adding R to your toolkit, how to install it, and the mechanics of the console, scripts, and R’s basic building blocks — the foundation the rest of the module builds on.

Learning Objectives

By the end of this chapter you should be able to:

  1. Explain what R is and why we are using it in addition to Excel.
  2. Install R and Positron, and run a simple R script.
  3. Save values as objects and run functions on them.
  4. Describe R’s basic data structures: vectors, data frames, and functions.
  5. Save a script that someone else can run from scratch and get the same results.

4.1 Why R? (And Why Also Excel?)

You just spent a module getting comfortable with Excel. Now I am going to tell you to put it down and learn a new tool.

Excel is an excellent tool for what it was designed to do: small-to-medium calculations where you can see every number on the screen, exploratory work, and handoffs to non-technical colleagues. But it has serious limitations:

  • Reproducibility. An Excel workbook is a tangle of cells; there is no record of what order things were done in. If you want to re-run an analysis on new data, you have to click through the whole thing again.
  • Scale. Excel caps out at a bit over a million rows per sheet and slows to a crawl well before that. Real datasets are often larger.
  • Composability. Doing the same operation (e.g., compute summary statistics) on fifteen different files in Excel means clicking through the same steps fifteen times.
  • Advanced statistics. Excel can do \(t\)-tests and linear regression, but the further you move from basic statistics, the worse a choice it is.

R is a programming language designed for statistical computing. R fixes every one of the limitations above. Your analysis is a script — a plain-text file that can be re-run, shared, version-controlled, and composed with other scripts. You can handle datasets of tens of millions of rows without trouble. You get access to thousands of packages written by statisticians around the world.

Learning R means learning to program. Writing code is a superpower – you are no longer limited to using the apps someone else has developed – you can now be the developer. And this skill is about to become enormously more powerful, not less, because of AI. It is tempting to think “why learn to code when AI can write the code for me?” — but that has it backwards. AI is a spectacular amplifier for people who understand programming, just like a calculator is an amplifier for those who already understand basic mathematical operations.

  • R for Data Science (2nd ed.) — the free, standard R textbook by Hadley Wickham and colleagues. The Introduction lays out what data science is and the workflow (import → tidy → transform → visualize → model → communicate) we will follow.
  • Video — R Programming 101, Why you should use R — a short, beginner-friendly pitch for learning R; a good first-day hook.

4.2 Installing R and Positron

You need two pieces of software to work with R:

  1. R itself — the language and the program that runs your code. Download it from CRAN (the Comprehensive R Archive Network), https://cran.r-project.org/.

  2. Positron — the editor we will use to write R code. Download from https://positron.posit.co/ and install it. Install R first, then Positron, so Positron can find your R.

You can think of an editor as being a bit like a web browser. Chrome, Firefox, and Safari all read HTML code and show you a website. Similarly, different editors (Positron, RStudio, VS Code) are all capable of running code in the R language. My sense is that RStudio was previously the most common choice as an editor, but Positron – which was developed by the same company as RStudio – may quickly supplant it. One reason for this is that using AI tools is a bit easier in Positron.

When Positron first opens you will see its Welcome screen, which looks something like this:

Figure 4.1: The Positron Welcome screen.

4.3 The Console

At the bottom of the screen is the console, where you can directly type commands and have R process them for you. In the screenshot below I’ve typed in some random equations and we can see that R functions as a fancy calculator (following the typical order of operations):

Figure 4.2: Doing arithmetic directly in the console. Type an expression, press Enter, and R prints the result on the next line.

One thing you will see in the output: each answer is printed with a [1] in front, like [1] 9. That [1] is just R noting that the value shown starts at position 1 of the result — it matters only when a result is a long list of numbers printed across several lines. For a single value you can ignore it.

Saving answers as objects

A calculator forgets each answer as soon as it shows it. R does better: you can save a value under a name and reuse it later. This is the single most important idea in R.

You save a value with the assignment operator, <- (a less-than sign and a dash, meant to look like a left-pointing arrow). You can also use the = sign, but it is good coding practice to reserve the equals sign for other operations. The thing you save is called an object. In the screenshot below I saved a as an object equal to 4 and b as an object equal to a*10.

Figure 4.3: Saving objects in the console with <-. Each object (a, b) appears in the Variables pane on the right as soon as it is created.

As you create objects, they appear in Positron’s Variables pane on the right (the panel that lists everything you have created). In the screenshot, you can see a and b show up with their values as soon as they are assigned.

An object can hold more than a single number. In the screenshot below, I save a vector of five values in an object called yields using the function c(), which combines values. I can then perform operations on yields like calculating its mean.

INSERT SCREENSHOT

The whole rhythm of R is just this: create objects with <-, and run functions on them. Sometimes we will save the results as new objects when we want to keep them, and we may perform operations on these objects.

Why not just work in the console?

4.4 R Scripts

You should only ever type code directly into the console (as we did above) for quick, throwaway calculations. For any real analysis — anything you want to re-run, check, share, or hand in — you need your code written down in a file you can save. That file is called a script, and it is the subject of the next section.

A script is a plain text file (ending in .R) where you write and save your code. The script is the permanent recipe for your analysis: you edit it, save it, and can re-run the whole thing later or share it with someone else.

Creating and running a script

Open Positron and create a new file with File → New File, then choose R File from the menu that appears:

Figure 4.4: Creating a new R file. File → New File opens this menu; choose R File.

Save it as hello.R (or whatever you want), then type (or paste) the following:

# My first R script
# Author: your name
# Date: 2026-09-15

print("Hello, world!")
2 + 2
x <- c(1, 2, 3, 4, 5)
mean(x)

Here is the crucial thing that trips up beginners: writing code in the script does not run it. Typing these lines just puts text in a file. Look at the script below — the code is written, but the console is still empty and no objects exist yet in the Variables pane:

Figure 4.5: Code written in the script (top), but not yet run. The console is empty and the Variables pane says “No variables have been created” — writing code does not run it.

To actually run it, you have a two different options:

  1. Click the Run button in the top right and either source the whole code to run all lines of your code, or “Execture code” to run just the selected lines (or the current line if noting is selected).

  2. A faster way to run code is to just type Cmd+Enter (Mac) / Ctrl+Enter (Windows).

After running all lines, the results appear in the console, and any objects you created show up in the Variables pane:

Figure 4.6: After running the script, the console shows the results and the Variables pane lists the objects that were created. Running the code is what makes things happen.

Let’s break down what just happened:

  • Comments start with # and are ignored by R. Use them liberally to explain your code.
  • print("Hello, world!") prints text to the console.
  • 2 + 2 evaluates an expression, just like in the console. R prints the result automatically.
  • x <- c(1, 2, 3, 4, 5) is the “save an object” step you met in the console: it creates a vector of the numbers 1 through 5 and stores it under the name x. (You can write = instead of <-, but <- is traditional in R and I recommend it.)
  • mean(x) is the “run a function on an object” step: it calls the mean function on x and hands back the result.

We should also note that the object x is now stored in R, and it will be stored until we exit this session or overwrite x with a new value.

This will be the last screen shot of Positron that I will show in the textbook. From now on I will just show the code, and sometimes the results of this code.

4.5 R Basics: Types, Vectors, Data Frames, Functions

R works by having you store objects—which include simple numbers, vectors, matrices, data frames, regression models, charts, and more. To get started with data, we will learn about two of these objects: vectors and data frames.

Objects contain values of different types. Common types include character (text), numeric (numbers), and logical (TRUE/FALSE). Somewhat confusingly, the components of an object can themselves have different types. For example, a data frame consists of columns, and each column can contain a different type of data.

Vectors

A vector is R’s basic data structure. It is a sequence of values of the same type (all numbers, or all strings, etc.). You create one with c():

yields <- c(48, 52, 47, 55, 50)
varieties <- c("InVigor", "DK", "Clearfield", "InVigor", "DK")
is_irrigated <- c(TRUE, FALSE, FALSE, TRUE, FALSE)

If a vector is numeric then we can do arithmetic operations on it. For example, say we have a vetor of yields in bu per acre and we want to convert it to tonnes per hectare, we can simply multiply the entire vector by a constant conversion factor.

Data Frames

A data frame is R’s word for a table: rows are observations, columns are variables. This is the main thing we will work with in this class

You can create one by hand, by combining vectors as in the following example:

fields <- data.frame(
  field_id = c("F01", "F02", "F03", "F04", "F05"),
  region = c("South", "South", "Central", "North", "North"),
  yield = c(48, 52, 47, 55, 50)
)
fields
> fields <- data.frame(
+   field_id = c("F01", "F02", "F03", "F04", "F05"),
+   region = c("South", "South", "Central", "North", "North"),
+   yield = c(48, 52, 47, 55, 50)
+ )
> fields
  field_id  region yield
1      F01   South    48
2      F02   South    52
3      F03 Central    47
4      F04   North    55
5      F05   North    50

But you will almost usually read a data frame from a CSV file. More on that in a moment.

You can access columns with the $ operator. For example, to get the column yield in our data frame fields we would type fields$yield. You will even note that when you type fields$ Positron will provide a dropdown of all the columns that you can choose from.

fields$yield        # the yield column as a vector
mean(fields$yield)  # mean yield

fields$yield <- c(58, 62, 57, 65, 60) ##Reset the value of the yield column
mean(fields$yield)  # get the mean yield of the updated column
> fields$yield        # the yield column as a vector
[1] 48 52 47 55 50
> mean(fields$yield)  # mean yield
[1] 50.4
> 
> fields$yield <- c(58, 62, 57, 65, 60) ##Reset the value of the yield column
> mean(fields$yield)  # get the mean yield of the updated column
[1] 60.4

You can also extract any part of the data frame using square brackets denoting the row first then a comma then the column. If you want a whole row, then leave the column blank, and vice-versa.

fields[1, ]         # first row
fields[, 1]         # first column
fields[2, 3]        # in the second row, third column
> fields[1, ]         # first row
  field_id region yield
1      F01  South    58
> fields[, 1]         # first column
[1] "F01" "F02" "F03" "F04" "F05"
> fields[2, 3]        # in the second row, third column
[1] 62

Functions

R largely operates by performing functions on objects. We have already seen that there is a function called mean(). There are a near infinite kinds of functions.

R functions generally require arguments. For example, in mean(fields$yield), the function is mean() and the function’s arugment is fields$yield.

Here the functions that we can use to get the descriptive statistics we learned in Excel in the last chapter You call a function by writing its name followed by parentheses with arguments:

mean(fields$yield)       # Mean
median(fields$yield)     # Median
max(fields$yield)-min(fields$yield) #Range
var(fields$yield)        # Variance
sd(fields$yield)         # Standard deviation
sd(fields$yield)/mean(fields$yield) # Coefficient of variation
> mean(fields$yield)       # Mean
[1] 60.4
> median(fields$yield)     # Median
[1] 60
> max(fields$yield)-min(fields$yield) #Range
[1] 8
> var(fields$yield)        # Variance
[1] 10.3
> sd(fields$yield)         # Standard deviation
[1] 3.209361
> sd(fields$yield)/mean(fields$yield) # Coefficient of variation
[1] 0.05313512

Some functions require multiple arguments. For example, the function quantile will return the value of a particular percentile. A properly written code will be quantile(x, percentile) where x is the object and percentile is the percentile that you want to find (expressed in decmial form).

There are two ways to write the function so that it will execute. First, write the arguments in the correct order without naming them. Second, name the arguments in the function – that is say x=fields$yield and percentile=0.25.

quantile(fields$yield, 0.25)  # The 25th quantile (the first quartile)

quantile(0.25, fields$yield) # The same function with unnamed arguments in the wrong order

quantile(probs=0.25, x=fields$yield) # The same function with named arguments in the wrong order
> quantile(fields$yield, 0.25)  # The 25th quantile (the first quartile)
25% 
 58 
> 
> quantile(0.25, fields$yield) # The same function with unnamed arguments in the wrong order
Error: 'probs' outside [0,1]
> 
> quantile(probs=0.25, x=fields$yield) # The same function with named arguments in the wrong order
25% 
 58 

To get help on a function, type ?function_name:

?mean

R will show you the documentation — what the function does, what its arguments mean, what it returns. Read it. R’s documentation is sometimes terse but always authoritative.