Course contents
Part IChapter 3R foundations and data
Your First R Instructions
On this page
- 1. Calculations
- 2. Variables: Give a result a name
- 3. Text, numbers, and TRUE/FALSE
- 4. Integer, double, and the special values
- 5. Functions: Give R a job
- 6. Math functions
- 7. What is an object? typeof(), class(), and attributes
- 8. Comparisons and logical values
- 9. Comments and reading errors
- Try it
- Checkpoint
1. Calculations
Arithmetic operators work like a calculator: + adds, - subtracts, * multiplies, / divides, and ^ raises to a power. Parentheses control what happens first.
2 + 3
Output
[1] 510 / 2
Output
[1] 5(4 + 6) * 2
Output
[1] 20(4 + 6) / 2
Output
[1] 5Predict the result of each line before running it.
Two more operators are useful with whole numbers. %% gives the remainder after division, and %/% gives the whole-number part of a division. They help with questions such as “is this number even?” or “how many full weeks are in 100 days?”
2 ^ 3 # 2 to the power 3
Output
[1] 817 %% 5 # remainder of 17 divided by 5
Output
[1] 217 %/% 5 # how many whole 5s fit in 17
Output
[1] 3100 %/% 7 # full weeks in 100 days
Output
[1] 14100 %% 7 # days left over
Output
[1] 217 %% 5 prints 2 because 17 is three 5s (15) plus 2, and 17 %/% 5 prints the 3.
2. Variables: Give a result a name
R’s assignment symbol <- means “store the value on the right under the name on the left.” It does not mean “the two things are equal forever.”
age <- 54
age # Read the stored value
Output
[1] 54age_next_year <- age + 1
age_next_year
Output
[1] 55age <- 55 # Replaces the previous age value
Running age <- 55 makes the name age point at 55 and drops 54, while age_next_year keeps the 55 it was given.
R also accepts a single = for assignment, so this works too:
age = 54
age
Output
[1] 54It prints 54, the same as with <-. This course uses <- for assignment because it is the common R style and our convention, not because = is wrong. It also lets = keep one job, naming arguments inside a function (as in digits = 2 below), while == compares.
Names are case-sensitive: Age and age are different objects. Prefer descriptive lowercase names with underscores (for example, systolic_bp). Avoid spaces in object names.
3. Text, numbers, and TRUE/FALSE
R handles several fundamental data types:
- numeric:
2,2.5, or-10. - character: text enclosed by quotation marks, such as
"North". - logical:
TRUEorFALSE, without quotation marks. - missing (
NA): an unknown value; not the same as zero.
weight_kg <- 70.5
clinic <- "Mobile"
is_adult <- TRUE
missing_bmi <- NA
class(weight_kg)
Output
[1] "numeric"class(clinic)
Output
[1] "character"class(is_adult)
Output
[1] "logical"is.na(missing_bmi)
Output
[1] TRUEThe three class() lines print "numeric", "character" and "logical", and is.na(missing_bmi) prints TRUE because that value is unknown. Note that "Mobile" needs quotes but TRUE does not.
A numeric-looking identifier such as "00123" should often remain text. Identifiers are labels, not measurements to average.
4. Integer, double, and the special values
Numbers come in two types. A double is a number that may have decimals; plain numbers you type, such as 5, are doubles. An integer is a whole number, and you make one by adding L, as in 5L. typeof() shows the stored type. For everyday work you rarely need to care, but counts such as length() are integers, and you will see “integer” and “double” in tables and error messages.
typeof(5)
Output
[1] "double"typeof(5L)
Output
[1] "integer"typeof(2.5)
Output
[1] "double"class(5L)
Output
[1] "integer"R also has special values that are not ordinary numbers:
Infand-Inf: infinity, from dividing a nonzero number by zero.NaN: “not a number”, from an undefined calculation such as0 / 0.NULL: nothing at all, an empty object. It is not the same asNA, which is a missing value in a place where a value belongs.
1 / 0
Output
[1] Inf-1 / 0
Output
[1] -Inf0 / 0
Output
[1] NaNis.nan(0 / 0)
Output
[1] TRUElength(NULL)
Output
[1] 0length(NA)
Output
[1] 11 / 0 prints Inf, 0 / 0 prints NaN, and length(NULL) is 0 while length(NA) is 1, because NA still occupies one slot. If a calculation on clinic data returns Inf or NaN, look for a zero in the denominator, such as a height of 0.
5. Functions: Give R a job
A function is a named operation followed by parentheses. Values inside the parentheses are called arguments. Some arguments have names.
round(3.14159, digits = 2)
Output
[1] 3.14sqrt(81)
Output
[1] 9sum(2, 5, 8)
Output
[1] 15round(3.14159, digits = 2) prints 3.14, sqrt(81) prints 9 and sum(2, 5, 8) prints 15. In the first call, digits is the name of the second argument, and 2 is its value.
Type help("round") in your own Console to open the help page for a function. It is shown here, not run, because it opens a help page rather than printing a result.
help("round")
When you see round(3.14159, digits = 2), read it aloud as “round 3.14159 to two digits after the decimal point.”
6. Math functions
R has the usual math functions built in. Each takes a number (or a whole vector of numbers) and returns a number.
x <- 7.58
round(x, 1) # nearest tenth
Output
[1] 7.6ceiling(x) # round up to a whole number
Output
[1] 8floor(x) # round down
Output
[1] 7trunc(-x) # drop the decimals, toward zero
Output
[1] -7sqrt(49)
Output
[1] 7exp(1) # e to the power 1
Output
[1] 2.718282log(100) # natural logarithm
Output
[1] 4.60517log10(100) # base-10 logarithm
Output
[1] 2log2(8) # base-2 logarithm
Output
[1] 3factorial(5) # 5 * 4 * 3 * 2 * 1
Output
[1] 120sin(0)
Output
[1] 0cos(0)
Output
[1] 1ceiling(7.58) is 8 and floor(7.58) is 7. trunc(-7.58) is -7 (toward zero), whereas floor(-7.58) would be -8. log(100) is about 4.6, but log10(100) is exactly 2. sin() and cos() work in radians and are rarely needed in clinic data; log() is the one you will meet most, for skewed measurements.
7. What is an object? typeof(), class(), and attributes
Everything you store in R is an object: a number, a piece of text, a vector, or later a whole table. Two questions describe an object. typeof() says how it is stored inside R, and class() says what kind of thing it is for the functions that use it. Often they agree, but not always (a factor is stored as integers).
An object can also carry extra labels called attributes, such as names. attributes() lists them and attr() reads or sets one.
pulse <- c(a = 70, b = 82)
typeof(pulse)
Output
[1] "double"class(pulse)
Output
[1] "numeric"attributes(pulse)
Output
$names
[1] "a" "b"attr(pulse, "units") <- "beats/min"
attr(pulse, "units")
Output
[1] "beats/min"attributes(pulse)
Output
$names
[1] "a" "b"
$units
[1] "beats/min"attributes(pulse) first lists only $names ("a" and "b"); after the attr() line it lists $units too. You rarely write attributes yourself, but this is where a factor keeps its levels and a table keeps its column names.
8. Comparisons and logical values
Comparison operators produce TRUE or FALSE. Use == to compare values; do not confuse it with <- to assign. Other comparisons are >, <, >=, <=, and !=.
age <- 54
age >= 18
Output
[1] TRUEage == 54
Output
[1] TRUEage != 54
Output
[1] FALSE(age > 40) & (age < 65) # Both conditions must be true
Output
[1] TRUE(age < 20) | (age > 50) # Either condition may be true
Output
[1] TRUEWith age equal to 54, the five lines print TRUE, TRUE, FALSE, TRUE and TRUE. The last one is TRUE because the second condition, age > 50, holds even though age < 20 does not.
R uses & for “and” and | for “or” when comparing vectors element by element.
9. Comments and reading errors
Text after a # is for humans; R does not execute it.
# This is a useful explanation for your future self.
bmi <- 27.2
bmi * 2
Output
[1] 54.4R skips the comment line, stores 27.2 under bmi, and prints 54.4. Typing bmii * 2 instead would give “object ‘bmii’ not found”, because that name was never created.
If R prints “object not found,” check whether you created that object, ran the earlier lines, and used the exact capitalization. If it prints “unexpected symbol,” look for missing quotation marks, commas, and parentheses.
Try it
- Calculate a BMI from weight 72 kg and height 1.65 m: weight divided by (height squared). Save each input in a named object.
Show solution to question 1
Answer: The BMI is about 26.4 kg/m².
Step by step
- Store each input under its own name.
- Divide the weight by the squared height.
weight_kg <- 72
height_m <- 1.65
bmi <- weight_kg / height_m^2
bmiOutput
[1] 26.446283. The Console prints the BMI. The ^ does the squaring first, so we divide by 2.7225 and get 26.44628. Reporting it as 26.4 is enough.
- Create a logical object called
high_bmithat isTRUEif BMI is at least 30.
Show solution to question 2
Answer: high_bmi is FALSE, because 26.4 is below 30.
Step by step
- Use the
bmiobject from the last item and the comparison>=.
bmi <- 72 / 1.65^2
high_bmi <- bmi >= 30
high_bmiOutput
[1] FALSE2. The comparison returns one TRUE or FALSE, which is stored under the name high_bmi.
3. It prints FALSE. A BMI of exactly 30 would give TRUE, because >= includes the boundary.
- Explain why
patient_id <- "00123"is different frompatient_id <- 123.
Show solution to question 3
Answer: "00123" is a character label that keeps its leading zeros, while 123 is a number; an ID in quotes is a label, and a number falsely implies that arithmetic on it is meaningful.
Step by step
- Store both versions and check their classes.
id_text <- "00123"
id_number <- 123
class(id_text)Output
[1] "character"class(id_number)Output
[1] "numeric"id_textOutput
[1] "00123"id_numberOutput
[1] 1232. The first is "character" and the second is "numeric". The number printed has lost its two zeros.
3. An ID is a name, not a measurement. Averaging patient IDs gives nonsense, and losing a leading zero can make two IDs look the same or fail to match another file.
- Intentionally mistype a name, read the error, then fix it.
Show solution to question 4
Answer: A mistyped name such as bmii gives “object ‘bmii’ not found”; fixing it means using the name that was actually created, bmi.
Step by step
- Create the object, then use a wrong name. The chunk below catches the error so the page can show its message.
bmi <- 26.4
msg <- tryCatch(bmii * 2, error = function(e) conditionMessage(e))
msgOutput
[1] "object 'bmii' not found"2. The message says object bmii was not found. R has no such name because we created bmi.
3. Fix the spelling.
bmi * 2Output
[1] 52.84. It prints 52.8. At the Console you would see the same message in red; check spelling, capitalization and whether the earlier line was run.
- Find the remainder and the whole-number part of 250 divided by 7. Then check
typeof(250)andtypeof(250L).
Show solution to question 5
Answer: The remainder is 5 and the whole-number part is 35; 250 is a double and 250L is an integer.
Step by step
- Use
%%for the remainder and%/%for the whole-number part.
250 %% 7Output
[1] 5250 %/% 7Output
[1] 352. 35 sevens make 245, and 250 - 245 leaves 5. 3. Check the types.
typeof(250)Output
[1] "double"typeof(250L)Output
[1] "integer"4. A plain number is stored as a "double"; adding L makes it an "integer".
- Predict, then run:
0 / 0,1 / 0,length(NULL). Say what each special value means.
Show solution to question 6
Answer: 0 / 0 is NaN (not a number), 1 / 0 is Inf (infinity), and length(NULL) is 0 because NULL is an empty object.
Step by step
- Predict first: zero divided by zero is undefined, a positive number divided by zero grows without limit, and
NULLmeans nothing. - Run them.
0 / 0Output
[1] NaN1 / 0Output
[1] Inflength(NULL)Output
[1] 03. The output matches. In clinic data, Inf or NaN usually means a zero in the denominator. NULL differs from NA: length(NA) is 1, because NA is a missing value that still occupies a slot.
- For the value 3.7, calculate
round(),ceiling(),floor(),trunc(),sqrt(), andlog10(). Also calculatefactorial(4).
Show solution to question 7
Answer: round() gives 4, ceiling() 4, floor() 3, trunc() 3, sqrt() about 1.92, log10() about 0.568, and factorial(4) is 24.
Step by step
- Store the value once, then apply each function.
x <- 3.7
round(x)Output
[1] 4ceiling(x)Output
[1] 4floor(x)Output
[1] 3trunc(x)Output
[1] 3sqrt(x)Output
[1] 1.923538log10(x)Output
[1] 0.5682017factorial(4)Output
[1] 242. round() goes to the nearest whole number, 4, and ceiling() always goes up, also 4. floor() and trunc() both give 3 for a positive number.
3. sqrt(3.7) and log10(3.7) print the decimals shown. factorial(4) is 4 * 3 * 2 * 1 = 24.
- Create
bp <- c(120, 135), give it an attribute called"units"with the text"mmHg", and printattributes(bp). Also say why this course writesx <- 5rather thanx = 5.
Show solution to question 8
Answer: attributes(bp) lists $units with the value "mmHg". The course writes <- so that <- always means assign, = names arguments, and == compares.
Step by step
- Make the vector and set the attribute with
attr().
bp <- c(120, 135)
attr(bp, "units") <- "mmHg"
attributes(bp)Output
$units
[1] "mmHg"2. The output has one entry, $units, holding "mmHg". The values are unchanged, and the label travels with the object.
3. Both x <- 5 and x = 5 work. Keeping <- for assigning leaves = for the digits = 2 style of argument and == for comparison, so each symbol has one job.
Checkpoint
You can assign values, use built-in functions, write comments, compare values, and understand the first error messages.