verb(object, argument = specification)Functions that make the work
Session 1 practical exercises
Your head of department, Kassandra, has just handed you a small sample of the unit’s surveillance data set (imd_S1.xlsx) — a few dozen cases from the invasive meningococcal disease registry. They are still working on your data permit, but this very little linelist can be useful for you to become acquainted with the data, and do a bit of practice before the actual work begins in a few days
“Get familiar with it”, she said. Before any analysis, before any cleaning, before any conclusions: you need to know what you are working with. That is what this exercise is about. If you haven’t done it yet, go to the data set page to learn about the data you will be using through this course.
Make sure imd_raw is loaded in your Environment before you start. If it is not, go back to E2 and re-run your import lines.
Part 7 · Functions as Grammar Models
What is a function?
You have already used several functions: here::here(), rio::import(), pacman::p_load(). But what exactly is a function?
Think back to your language classes. A sentence needs a verb — an action word — to mean anything. “Run”, “calculate”, “summarise” — verbs tell you what is happening. In R, functions are verbs. They tell R what action to perform.
This is the Grammar Model we will use throughout the course:
Writing code is the art of giving precise instructions. Every instruction has a verb (the function), something to act on (the object), and sometimes additional specifications (the arguments).
- In plain English: “Calculate the mean of age, removing missing values.”
- In R:
mean(imd_raw$age, na.rm = TRUE)
The parallel is exact:
| Grammar | R code | Example |
|---|---|---|
| Verb | Function name | mean |
| Object | What you act on | imd_raw$age |
| Modifier | Named argument | na.rm = TRUE |
This model will not change. Every function you learn from here on fits this structure — the verbs will multiply, but the grammar stays the same.
The language analogy also applies to spelling, R will not understand if you type mena instead of mean.
R is case-sensitive, it will not understand MEAN or Mean, only mean.
Your first verbs
Let us start with three simple functions that ask questions about your data set:
Action — Run these lines one by one and read what R tells you:
nrow(imd_raw)
ncol(imd_raw)
names(imd_raw)Each of these is a verb acting on the same object (imd_raw) but asking a different question:
nrow()— “How many rows does this have?”ncol()— “How many columns does this have?”names()— “What are the column names?”
Notice that none of these need additional arguments. The object alone is enough. Some verbs are simple — just an action and a target.
In the Grammar Model, what does the function name represent?By the way, did you realize how the previous functions created different outputs? nrow() and ncol() just produced one number - the answer to the question is just that; but names() produced something different, an answer with more than one reply. Because there is more than one column, the answer to that question has to be all existing names
In R this is called a vector
Part 8 · Vectors and columns
Vectors are a sequence of values living together in a single object. R is a vectorised programming language, meaning that information is processed though these. In fact, your entire dataframe is built as a collection of columns representing variables, with each column constituting a vector itself.
A dataframe is a collection of vectors
When you ran names(imd_raw), R listed the column names of your dataframe. Each of those columns is a vector — a sequence of values of the same type.
Think of a dataframe as a table where: - Each row is one observation (one case) - Each column is one variable — and that column is a vector
This means your dataframe imd_raw is not one object — it is many vectors living together in a shared structure. To extract a single column from a dataframe, use the $ operator like this:
imd_raw$ageThis tells R: “From the object imd_raw, give me the column called age.” R will print all the values in that column.
Action — Extract a few more columns and observe what R returns
Notice when you write the $ operator after the dataframe name, RStudio opens a little pop-up list containing the variable names. This can make it easier to navigate, and you can also start typing the name and the available names will narrow down to match your “search”
As any other piece of information in R, you could very well start from loaded data and extract one variable into a new object for further use. Let’s do it for the sake of teaching - and then you will understand why it wouldn’t be necessary in the first place
Action — Save the age of your cases in a new object named patients_age
And, since we have the object in our Environment, let’s show something else. Before, you used nrow() to ask how many observations/row the data had. Now we have a vector, and we want to know how many values it contains, for which we have a function called length()
Action — Compare the number of rows in imd_raw and the values contained in patients_age. Would you create an object for this action?
nrow(imd_raw)
length(patients_age)When should you store information in new objects and when should you just call the function to print the result?
This is not a minor question. Creating objects is the way of granting information is not lost. However, is it always necessary to keep the result? Sometimes you may just want to quickly check something, but the information serves no other purpose. So always think about the print vs assign key feature of R
Both functions should return the same number — because each column has exactly one value per row, thus making the number of rows identical to the number of items contained in the vector of the age column of the data
What is a vector in R?Part 9 · Numeric functions on vectors
Now that you know how to extract a column, you can apply functions to it. This is where R starts to become genuinely useful. During the presentation, we saw the functions mean() and sum() in action. Now it’s your turn:
Action — What is the mean age of your current cases? Use your age object and the data column and compare the result
As you can see, there is no point in creating an intermediate object when you can directly access the data using the $ operator. This is usually the quickest way of accessing information within dataframes, and dataframes will be our main working objects for data analysis
Let’s try a few more numeric functions, to see their different outputs
Action — Run these functions on the age column:
mean(imd_raw$age)
sum(imd_raw$age)
min(imd_raw$age)
max(imd_raw$age)
range(imd_raw$age)
quantile(imd_raw$age)
table(imd_raw$age)Read the output of each one carefully. Notice that range() returns two values and quantile() returns five — vectors can hold multiple values, and functions can return multiple values. Each of those functions is answering a very specific question. Think about their Grammar Model
Exercise summary
You are done with the Session 1 practicals. You now have a working R Project, your packages loaded, your data imported, and your first functions under your belt. In Session 2 you will meet Kassandra, and you will learn about the true power of R: the Tidyverse.
This is what you practiced and learned:
| Grammar Model | Function = verb, object = what to act on, arguments = modifiers |
nrow() , ncol() , names() |
Ask basic questions about a dataframe’s structure |
$ |
Extracts a column from a dataframe as a vector |
class() |
Returns the type of an object or column |
length() |
Returns the number of elements in a vector |
mean() , sum() , min() , max() |
Numeric summaries of a vector |
range() , quantile() |
Return multiple values describing the distribution |
table() |
Counts occurrences of each value in a categorical vector |