Tutorial 1
Installing R
First, you need to download and install the latest version of R.
- Go to R official website
- Click on “download R”
- Save the installation file
- Run the installation file and follow the prompts to install R (default settings are fine)
Installing RStudio
- Go to RStudio
- Click the big blue download button to download the installation file
- Run the installation file and follow the prompts to install RStudio (default settings are fine)
Cheatsheets
If you forget how to use it or are not sure, there are some cheatsheets for you: RStudio cheatsheet
Scientific computing
- Q1: Write a function to solve a quadratic equation
\[ ax^2+bx+c=0 \]
Using only material covered so far (warns when the discriminant is negative):
With flow control (later lecture): return NaN when b^2 - 4*a*c < 0.
Lab overview
You have been hired to audit the sales records of the Downtown Pop-Up Market, which sold Snacks, Drinks, Merch, and Stickers over a three-day weekend.
Work through each section by running the code examples and answering the questions. Answer keys and worked code are in hidden instructor blocks on the live page (and in the teacher-notes pack).
1. Vector arithmetic and recycling
Before opening, the store set these standard retail prices:
- Snacks: $12
- Drinks: $5
- Merch: $35
- Stickers: $4
Scalar broadcasting vs. vector operations
Run the following chunk. You will use base_prices for the rest of this lab.
- Add 12.5% sales tax to each product’s base price. Store the result in
taxed_prices. The tax rate is already given below.
- Apply the discount rates in
discount_ratesto the base prices (not the taxed prices). Store the result indiscounted_prices.
After you have created taxed_prices and discounted_prices, run this chunk to build a data frame named price_df:
Questions
What does R do when you multiply a vector of length 4 by a single number such as
(1 + tax_rate)(a vector of length 1)?Suppose you scramble the names of
discount_ratestoc(Stickers = 0.20, Merch = 0.15, Drinks = 0.00, Snacks = 0.05)but leavebase_pricesin the original order. Do the usual arithmetic operators (*,+, …) match values by name or by position (1st with 1st, 2nd with 2nd)?
Answer key
Recycling (often called broadcasting here). R has no separate scalar type:
1 + tax_rateis an atomic vector of length 1. R recycles that single value to length 4 so pairwise multiplication can run.By position, not by name. Binary arithmetic ignores names. Index 1 multiplies with index 1, and so on. If
discount_ratesis reordered andbase_pricesis not, the wrong discount is applied. To align by name you would need something likediscount_rates[names(base_prices)].
Indexing
Extract the Sale_Price column from price_df. Hint: there are several valid approaches; try more than one.
To read the cell in row 3, column 3, you can use either of these:
Questions
Compare
price_df[3, 3]withprice_df["Merch", "Sale_Price"]. Which is easier for another reader to understand without looking at the data?Next month the store adds a column
SKU_Numberas column 1, so every later column shifts one place to the right. What wouldprice_df[, 3]refer to then, compared withprice_df[, "Sale_Price"]? Which is less sensitive to that change?Compare the printed result and
class()ofprice_df$Sale_Price,price_df["Sale_Price"], andprice_df[["Sale_Price"]]. Why does[without a comma return a one-column data frame, while$and[[extract a numeric vector?
Answer key
price_df["Merch", "Sale_Price"]is clearer: it names the row and the column.After inserting
SKU_Numberat the front,price_df[, 3]would be the old column 2 (Discount).price_df[, "Sale_Price"]still means sale price no matter how many columns you add, so it is the more robust choice.$and[[pull out the vector stored in that column.[with no comma subsets the data frame as a list of columns, soprice_df["Sale_Price"](andprice_df[3]for the third column) stays a one-columndata.frame.
Recycling rules and warnings
The market tests a packaging fee on the four catalogue items. Run the chunk below and inspect the output.
Questions
Why does adding
pack_fee_2(length 2) tobase_prices(length 4) run without a warning? What pattern of fees is applied to Snacks, Drinks, Merch, and Stickers?Why does adding
pack_fee_3(length 3) warn, and what values does R actually add to the four items?Why can “even” recycling (lengths that divide evenly) be more dangerous in an audit than the warning case?
Answer key
R recycles the shorter vector until it matches the longer one. When
length(longer) %% length(shorter) == 0(here \(4 \bmod 2 = 0\)), R treats the repeat as intentional and stays silent. The fees are \(+1, +2, +1, +2\).\(4 \bmod 3 \neq 0\), so R still wraps around (the fourth item gets the first fee, \(+1\)) but warns:
longer object length is not a multiple of shorter object length.If someone passed
c(5, 0), R would add $5 to Snacks and Merch and $0 to Drinks and Stickers with no warning. The code is valid, so the accounting error is easy to miss. The mismatched-length warning at least flags that something odd happened.
Finding help with ?
Inspect taxed_prices and round(taxed_prices):
Questions
Does
round(taxed_prices)match what you expected? Hint: look at values that sit exactly on.5, then try a few extra examples of your own.Type
?roundin the console and read the Details section.- Which international standard does R follow?
- How does that standard explain what you saw for
round(taxed_prices)?
Answer key
Half-way cases do not always round “away from zero” or “always up”. They follow round half to even (the adjacent even integer).
IEC 60559 / IEEE 754. That is why a
.5can round up or down depending on whether the neighbouring integer is even.
Data types and coercion
During peak hours, an employee types "PROMO" into the register price column instead of $0 for a free drink:
Questions
What is the data type of
"PROMO"on its own?After you build
register_logas above, what is the data type ofregister_log[1]? Can you computeregister_log[1] + register_log[3]?What is R’s usual coercion hierarchy for atomic vectors (from most specific to most flexible)?
Answer key
Character.
Character as well — one character value forces the whole vector to character — so
register_log[1] + register_log[3]is not valid numeric addition.\[ \text{logical} \longrightarrow \text{integer} \longrightarrow \text{double (numeric)} \longrightarrow \text{character} \]