1. A Small Detour and an Introduction
Welcome back.
My parents often remember that when I was very young, I had an almost childlike obsession with computers. It was like a first love, or at least a first fascination. Over the years, my view evolved: I went from thinking of computing as something magical to recognizing it as a system that is incredibly simple in its individual components, yet emergent and remarkably complex as a whole. Today, I think of it as a beautiful mix of both.
There is an entire field of theory dedicated to how computers process information, "think," and operate: computer science. And if you didn't know, bioinformatics is the intersection—the entire intersection—of computer science and biology.
Despite my initial fascination with machines, my first formal education was actually in the biosciences—a path shared by many in healthcare, and perhaps by you as well. However, I am confident that throughout these next chapters, I will be able to share the exact tools and concepts that were most instrumental in helping me transition into computational medicine and biomedical data science. In this particular lesson, we will cover the foundational building blocks of code: variables, assignment operators, vectors, and functions.
2. Variables
Variables are essentially named containers used to store information. While variables are covered in almost every introductory programming resource, I want us to look at them through a familiar healthcare concept to help you truly synthesize how they work.
Think of a disease process. A clinical diagnosis is a classification we assign to a patient based on their presentation in the clinic. When a patient walks in, you evaluate their presenting symptoms. The word "symptom" acts as a conceptual category in our minds, which we then pair with whatever physical findings the patient conveys.
This mapping is conceptually identical to how a variable pairs with a value:
- The Variable (The Category):
symptom - The Value (The Specific Data):
"sore throat"
Similarly, you might assign a numerical value to a physiological metric like heart rate or B-type natriuretic peptide (BNP). A reading of 110 beats per minute would be clinically classified as tachycardic, but computationally, the number 110 is simply the value stored inside the variable heart_rate.
In computer science, this relationship is formalized. A variable can hold a word, a single number, or a massive set of numbers. Any structured data can be assigned to a variable. To help us handle these data points cleanly and efficiently, the R programming language categorizes this information into a few fundamental data types (like integers, numerics, and characters).
3. Assignment Operators
The most recognizable assignment operator in the world is a symbol you are already familiar with from basic mathematics: the equals sign (=).
In many programming languages, including Python and R, the equals sign is used to pass a value into a variable. By convention, the variable receiving the data sits on the left side of the expression, and the value being assigned sits on the right side:
R
x = 4
print(x)
Executing this in your R console assigns the value 4 to the variable x and prints it to the screen.
However, when reading idiomatic R code, you will much more frequently see a different symbol used for assignment: the arrow operator (<-).
R
x <- 4
print(x)
This achieves the exact same result: it points the value 4 directly into the container x.
> ### 💡 R-Specific Pro Tip
>
> While both `=` and `<-` work similarly for basic operations, R documentation overwhelmingly favors the `<-` arrow operator for top-level assignments. The underlying operational differences between the two are minor and tied to scope, which we will explore in a later module. For now, get comfortable using the arrow!
4. Vectors
If a variable is a container for a single piece of information, a vector is a container that holds an ordered collection of data points. The defining specification of a vector is that it is strictly one-dimensional.
One-Dimensional (Vector): [ 4, 2, 3 ]
Two-Dimensional (Matrix): | 4 2 |
| 3 1 |
Vectors, and more.
For context, two-dimensional structures are called matrices, while three-dimensional arrays and higher are referred to as tensors
In R, vectors are the absolute bread and butter of data manipulation. A vector can hold many individual items, but by design, it is homogeneous—meaning all items inside a single vector must be of the exact same data type. You can have a vector of text strings, or a vector of numbers, but you shouldn't mix text and numbers together in the same vector.
To create a vector in R, we use a built-in shortcut called the combine function, written simply as c():
R
x <- c(4, 2, 3)
print(x)
The c() function bundles the numbers 4, 2, and 3 together into a single, one-dimensional block of data. Printing x outputs the complete sequence exactly in the order you provided it.
5. Functions
Functions are pre-written, reusable code blocks designed to perform specific tasks. Think of them as computational shortcuts: they take inputs (called arguments), execute instructions on those inputs, and return an output.
Just like text strings or numbers, a function itself is stored in R as a specialized type of object so it can be referenced and recalled later. Here is an anatomy breakdown of a custom function:
R
# Define the function and its expected inputs (x and y)
my_simple_adder <- function(x, y) {
z <- x + y
return(z) # Explicitly pass the result back out
}
# Call the function with real numbers and save the output
result <- my_simple_adder(2, 4)
print(result)
# [1] 6
Key Structural Concepts to Notice:
- The Declaration: We use the
functionkeyword followed by parentheses containing our inputs (x, y), and enclose the operational steps inside curly braces{ }. - The Return: The
return(z)statement explicitly dictates what output value should be sent back out to the rest of your program once the calculations are complete. - The Assignment: When we run
my_simple_adder(2, 4), the function calculates the answer and passes6directly into our new variable,result.
Most of the functions you will use in your biomedical career will be written by other developers—after all, in data science, we constantly stand on the shoulders of giants. However, learning to write your own functions forces you to think algorithmically. The real challenge isn't learning the syntax; it's knowing exactly what you want to accomplish and crystalizing that logic so it executes reliably every single time—even when fed unusual or unexpected data.