R, Positron and Projects
2026-09-10
Note
✅ Key idea
Today we take that tidy spreadsheet and bring it to life in R.
<- the assignment operator - alligator eats the minus sign…Tip
🖐 Try it yourself
By the end you will run real code on our leaf data — not a toy dataset.

Note
📖 New word
IDE = Integrated Development Environment. Think of R as the car engine and the IDE as the seat, wheel, and dashboard.

Make one folder per project. Everything for the tree experiment lives together:
tree_project/
├── data/ ← your Excel and CSV files
├── scripts/ ← your .R code files
└── figures/ ← plots you save
C:/Users/.../Desktop/... nightmaresNote
✅ Key idea
A tidy folder today saves an hour of “where did I put that file?” next week.
Note
📚 Reference
R for Data Science (2e), Ch. 6 — Workflow: scripts and projects. Covers exactly this: projects, relative paths, and “what is the source of truth.”
Note
📊 Coming from Excel?
Four panes you will use constantly:
Tip
🖐 Try it yourself

Type math straight into the console and press Enter:
R answers immediately. The console is great for quick “what is the answer?” questions.
Warning
⚠️ Watch out!
+ at the start of the console line means R is still waiting for you to finish a command.Note
📊 Coming from Excel?
=3+5 into an Excel cell<- assignment operator - alligator eats the minus signTo keep a value, give it a name with the assignment operator <-:
<- puts the value into your environment (look in the Variables pane!)<- for youNote
📖 New word
Assignment operator <- “puts the thing on right and stores it in the name on left.” Do not use =

Good names make code readable months later:
leaf_mass, not x2x2 ✅, 2x ❌mass_g ≠ Mass_glower_snake_case — words separated by underscoresWarning
⚠️ Watch out!
mass_g and mass_G are two different objects. Pick one style and stick with it. I URGE you to use lower case and underscores — lower_snake_case, always.
Note
📖 New word
Object (R) = variable (Excel/other languages). Same idea: a named container that holds something.
_df_plot_modelNote
📚 Reference
R for Data Science (2e), Ch. 2 — Workflow: basics (naming, calling functions) and Ch. 4 — Workflow: code style (spacing, pipes). Short chapters — worth reading both.
#Anything to the right of # is ignored by R — it is a note for humans:
Note
✅ Key idea
If a line confused you while writing it, comment why you did it.
Note
📊 Coming from Excel?
Comments are like the notes you scribble in a cell — but they never get in the way of the numbers or the code.
A function is a canned script you call by name. You feed it arguments (inputs); it returns a result:
Stuck on a function?
Note
📖 New word
Argument = an input you hand to a function inside its ( ).

A vector is a series of values built with c() (“combine”) or concatenated list:
Inspect any vector:
Warning
⚠️ Watch out!
Quotes matter: "sunny" is text. Without quotes, R hunts for an object named sunny and errors when it cannot find one.
Note
✅ Key idea
A vector is the workhorse of R. A spreadsheet column is really just a vector.
Every vector holds one type:
numeric — 4, 3.5character — "sunny"logical — TRUE / FALSEMix types and R quietly coerces them all to one:
Note
📖 New word
Coercion = R automatically converting everything in a vector to a single shared type.

The console forgets and you would have to retype all of your code over and over….
A script (.R file) remembers and re-runs code
Note
✅ Key idea

Like apps for your phone, packages add new abilities to R.
Install once — downloads to your computer (do this in the Console, not in your script):
Load every session — activates it for today (put this at the top of every script):
Warning
⚠️ Watch out!
If R says “could not find function read_excel”, you forgot the library(readxl) line.
Note
📖 New words
Put your files in the project’s data/ folder, then:
Note
✅ Key idea
read.csv() - comes with base r and can have issuesread_excel() - needs library(readxl).read_csv() - needs library(tidyverse)clean_names() - needs library(janitor); turns messy Excel headers like "Leaf Mass (g)" into tidy names like leaf_mass_g automaticallyNote
📊 Coming from Excel?
read_excel() and read_csv() are the bridge from your file into R. Your file’s first row becomes the column names in R.
Note
📚 Reference
R for Data Science (2e), Ch. 7 — Data import. Covers read_csv() in depth, including column types and messy real-world files.
A data frame is a table: each column is a vector of one type, and the rows line up.
Our tree_df has eight columns:
twig_id, leaf_id, teams — sample identifiers (character)shade — "sunny" / "shady" (character)mass_g, petiole_mm, thickness_mm, paper_mass_g (numeric)Pull a single column with $:
Note
📖 New word
Data frame = R’s word for a spreadsheet-style table.

Always eyeball a new data frame:
head(tree_df) # first 6 rows
tail(tree_df) # last 6 rows
dim(tree_df) # rows, columns → 41 8
names(tree_df) # column names
# Tidyverse-style structure check (prefer this over str):
glimpse(tree_df) # one line per column: name, type, first values
# Base R equivalent:
str(tree_df) # same information, different layoutTip
🖐 Try it yourself
Run glimpse(tree_df). How many rows? What type is shade?
Note
✅ Key idea
Check dim() and glimpse() every single time you load data. Typos and wrong column types hide here.
Warning
⚠️ Watch out!
If a number column shows as <chr>, a stray letter or comma snuck into your spreadsheet.
%>% — read it as “then”The pipe sends a result straight into the next function. Read %>% as the word “then”:
In Lecture 03 we will chain more steps together.
Note
📖 New word
Pipe %>% = “take what is on the left and feed it to the function on the right.”

Note
Two pipes — same idea:
%>% — from tidyverse (we use this one)|> — built into R 4.1+ (the “native pipe”)Plots are built from three core pieces, joined with +:
tree_df)+)Warning
⚠️ Watch out!
+ must sit at the end of a line, never the start.+ at the start = error%>% for code and + for plots, but that’s just how it is.Note
📚 Reference
R for Data Science (2e), Ch. 1 — Data Visualization, and Whitlock & Schluter, Ch. 2 — Displaying Data, on why we choose one graph type over another for a given kind of data.

Since shade is a category, a boxplot with the raw points on top tells the story well:
# define the point position ONCE, at the top, so every layer can reuse it
jitter_pos <- position_jitter(width = 0.15, seed = 42)
ggplot(tree_df, aes(x = shade, y = mass_g)) +
geom_boxplot() +
geom_point(position = jitter_pos, alpha = 0.6, color = "tomato") +
labs(x = "Side of tree",
y = "Leaf mass (g)",
title = "Sunny vs. shady leaves")Tip
🖐 Try it yourself
Swap mass_g for thickness_mm. What changes? Try geom_violin() instead of geom_boxplot().
Before you run it: sketch what you expect this plot to look like — boxes, dots, axes — then compare it to what R draws.
Note
Why position_jitter() in a variable?
geom_point() alone stacks every leaf on one vertical line. position_jitter(width = 0.15) nudges them sideways so you can see each one; seed = 42 keeps that random nudge identical every time you render. Storing it in jitter_pos means the next layer (a mean, an error bar, a connecting line) can sit at the exact same spot.
Store the plot in an object, then save it as a PNG:
.png) for reports and Canvas submissions.dpi = 300 means 300 dots per inch — high enough for print and posters.Warning
⚠️ Watch out!
ggsave() wants the filename first, then plot =. Also: dpi = 300 is publication quality — always use it.
Note

<-# comments?read_excel() and read_csv()glimpse(), head(), dim()%>% to chain stepsggplot as a PNGTip
🖐 Before next class
Load tree_df, run glimpse(), and make one plot of petiole_mm by shade. Save it to figures/.
Note
✅ Key idea
You went from a blank console to a saved figure of our data. That is the whole workflow in miniature.
Up next — Lecture 03 & 04 (Week 2):
ggplot2 in depth — stat_summary(), facet_wrap()/facet_grid(), scale_color_manual(), coord_cartesian(), and themes🛑 Go to Activity 2 — “Introduction to R and Positron”
Open the Activity 2 worksheet and work through it at your own pace, typing every code chunk into your own script in Positron. It repeats everything on these slides, in the same order, with blanks for you to fill in. Raise your hand if you get stuck — that is expected and normal.
Note
Both books are in the course readings/ folder.
When code breaks (it will — that is normal):
?function_name — the built-in help pagelibrary(tidyverse) and library(readxl)?) or +?Note
✅ Key idea
Every coder googles error messages daily. Getting stuck is not failing — it is the job. Your job is to learn, and learning means breaking things and figuring out why.
Note
📊 Coming from Excel?
In Excel you fix errors by clicking around. In R you fix them by reading the message and editing one line. Slower at first, far more powerful soon.