Practice Question 1
Lab overview
You have been hired to audit data from a recent fluorescence experiment. The research team recorded the baseline fluorescence intensity of four cellular markers (CD4, CD8, CD19, and CD56) over a three-day period.
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).
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).
About fluorescence experiment
1. Vector arithmetic and recycling
Before opening, the below experiement results has been recorded:
- CD4: 12
- CD8: 5
- CD19: 35
- CD56: 4
Scalar broadcasting vs. vector operations
Run the following chunk. You will use base_signals for the rest of this lab.
- Add a 12.5% signal amplification (from a secondary antibody) to each marker’s base signal. Store the result in
amplified_signals. The amplification rate is already given below.
- Over time, the signals naturally fade. Apply the fading rates in fade_rates to the base signals (not the amplified signals). Store the result in faded_signals.
After you have created amplified_signals and faded_signals, run this chunk to build a data frame named signal_df:
Questions
What does R do when you multiply a vector of length 4 by a single number such as
(1 + amp_rate)(a vector of length 1)?Suppose you scramble the names of
fade_ratestoc(CD56 = 0.20, CD19 = 0.15, CD8 = 0.00, CD4 = 0.05)but leavebase_signalsin 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 + amp_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
fade_ratesis reordered andbase_signalsis not, the wrong discount is applied. To align by name you would need something likefade_rates[names(base_signals)].
Indexing
Extract the Final_Signal column from signal_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
signal_df[3, 3]withsignal_df["CD19", "Final_Signal"]. Which is easier for another reader to understand without looking at the data?Next month a student adds a column
Sample_IDas column 1, so every later column shifts one place to the right. What wouldsignal_df[, 3]refer to then, compared withsignal_df[, "Final_Signal"]? Which is less sensitive to that change?Compare the printed result and
class()ofsignal_df$Final_Signal,signal_df["Final_Signal"], andsignal_df[["Final_Signal"]]. Why does[without a comma return a one-column data frame, while$and[[extract a numeric vector?
Answer key
signal_df["CD19", "Final_Signal"]is clearer: it names the row and the column.After inserting
Sample_IDat the front,signal_df[, 3]would be the old column 2 (Fade_Rate).signal_df[, "Final_Signal"]still means final signal 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, sosignal_df["Final_Signal"](andprice_df[3]for the third column) stays a one-columndata.frame.
Recycling rules and warnings
The core tests a background noise threshold correction on the four markers. Run the chunk below and inspect the output.
Questions
Why does adding
noise_2(length 2) tobase_signals(length 4) run without a warning? What pattern of fees is applied to CD4, CD8, CD19, and CD56?Why does adding
noise_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 CD4 and CD9 and 0 to CD8 and CD56 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 amplified_signals and round(amplified_signals):
Questions
Does
round(amplified_signals)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(amplified_signals)?
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, a technician types "SATURATED" into the instrument log instead of 0 for a blank well:
Questions
What is the data type of
"SATURATED"on its own?After you build
instrument_logas above, what is the data type ofinstrument_log[1]? Can you computeinstrument_log[1] + instrument_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
instrument_log[1] + instrument_log[3]is not valid numeric addition.\[ \text{logical} \longrightarrow \text{integer} \longrightarrow \text{double (numeric)} \longrightarrow \text{character} \]