Practice Question 1

Author

Dr. Yu Cheng Hsu

Published

October 8, 2026

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

Leukemia cells labeled with fluorescent molecules

Leukemia cells labeled with fluorescent molecules

Basic mechanism of immunofluorescence

Basic mechanism of immunofluorescence

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.

  1. 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.
  1. 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

  1. 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)?

  2. Suppose you scramble the names of fade_rates to c(CD56 = 0.20, CD19 = 0.15, CD8 = 0.00, CD4 = 0.05) but leave base_signals in the original order. Do the usual arithmetic operators (*, +, …) match values by name or by position (1st with 1st, 2nd with 2nd)?

Answer key

  1. Recycling (often called broadcasting here). R has no separate scalar type: 1 + amp_rate is an atomic vector of length 1. R recycles that single value to length 4 so pairwise multiplication can run.

  2. By position, not by name. Binary arithmetic ignores names. Index 1 multiplies with index 1, and so on. If fade_rates is reordered and base_signals is not, the wrong discount is applied. To align by name you would need something like fade_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

  1. Compare signal_df[3, 3] with signal_df["CD19", "Final_Signal"]. Which is easier for another reader to understand without looking at the data?

  2. Next month a student adds a column Sample_ID as column 1, so every later column shifts one place to the right. What would signal_df[, 3] refer to then, compared with signal_df[, "Final_Signal"]? Which is less sensitive to that change?

  3. Compare the printed result and class() of signal_df$Final_Signal, signal_df["Final_Signal"], and signal_df[["Final_Signal"]]. Why does [ without a comma return a one-column data frame, while $ and [[ extract a numeric vector?

Answer key

  1. signal_df["CD19", "Final_Signal"] is clearer: it names the row and the column.

  2. After inserting Sample_ID at 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.

  3. $ and [[ pull out the vector stored in that column. [ with no comma subsets the data frame as a list of columns, so signal_df["Final_Signal"] (and price_df[3] for the third column) stays a one-column data.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

  1. Why does adding noise_2 (length 2) to base_signals (length 4) run without a warning? What pattern of fees is applied to CD4, CD8, CD19, and CD56?

  2. Why does adding noise_3 (length 3) warn, and what values does R actually add to the four items?

  3. Why can “even” recycling (lengths that divide evenly) be more dangerous in an audit than the warning case?

Answer key

  1. 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\).

  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.

  3. 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

  1. 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.

  2. Type ?round in 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

  1. Half-way cases do not always round “away from zero” or “always up”. They follow round half to even (the adjacent even integer).

  2. IEC 60559 / IEEE 754. That is why a .5 can 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

  1. What is the data type of "SATURATED" on its own?

  2. After you build instrument_log as above, what is the data type of instrument_log[1]? Can you compute instrument_log[1] + instrument_log[3]?

  3. What is R’s usual coercion hierarchy for atomic vectors (from most specific to most flexible)?

Answer key

  1. Character.

  2. Character as well — one character value forces the whole vector to character — so instrument_log[1] + instrument_log[3] is not valid numeric addition.

  3. \[ \text{logical} \longrightarrow \text{integer} \longrightarrow \text{double (numeric)} \longrightarrow \text{character} \]