library(tidyverse)
df_DEG<-read_tsv("https://github.com/StatBiomed/BMDS-book/raw/main/notebooks/chapter1-R/Diff_Expression_results.tsv")Tutorial 2
Cheatsheets
If you forget ggplot2 syntax, here is a cheatsheet for your reference: ggplot2 Cheatsheet
Question Set 1
Background: Differentially expressed genes results Diff_Expression_results.tsv (or view here) to this folder. Check your current working directory using the getwd() function and change it to the newly created folder. Hint*: Use setwd("<path to R_exercises>") to change the working directory, replacing <path to R_exercises> with the actual path to the folder, or use the Session menu in RStudio to set the working directory.
- Q3: Use the
summary()function to get an overview of thedf_DEGdata frame.
Answer Key
- Q1: Create a histogram of the
log2FoldChangecolumn indf_DEGusing both the basic plotting functionhist()and theggplot2package. For the ggplot2 plot, add a figure titleHistogram of log2FoldChange.
Answer Key
- Q2: Create a scatter plot with the x-axis as
log10(baseMean)and the y-axis aslog2FoldChangefrom thedf_DEGdata frame. Use both the basicplot()function and theggplot2package.
Answer Key
- Q3: Manipulate the data frame by adding two columns:
- Add a column
log2FC_clipfor clippinglog2FoldChangeto the range[-5, +5]. - Add a column
is_DEto indicate ifpadj < 0.05.
- Add a column
Answer Key
- Q4: Use the
table()function to count the values in theis_DEcolumn.
Answer Key
- Q5: Using ggplot2, create a scatter plot colored by the newly added column
is_DE. To make the figure clear, set the color legend title toIs differentially expressedand map the labels fromTRUEtoYesandFALSEtoNo.
Answer Key
- Q6: For the scatter plot from Q8, reverse the color order so that
TRUE (Yes)is blue andFALSE (No)is red. How do you adjust the code? Hint: ggplot uses the order of factor levels to render the color. Usefactor()and set thelevelsparameter to control the order of categories.
Answer Key
- Q7: Save the scatter plot from Q8 or Q9 into a file named “My_DEG_results.pdf”.
Answer Key
Question Set 2
This question set focuses on clinical data manipulation using the birthwt dataset, including converting binary risk indicators to factors, implementing Leave-One-Out Cross-Validation (LOOCV) for disease/risk prediction, calculating logistic regression probabilities, and evaluating maternal-infant health risk factors.
First, we load the MASS package and the birthwt data:
library(MASS)
data <- birthwt
head(data)- Q1: To make the clinical data more interpretable, please change the column low to a factor such that 0 refers to normal weight and 1 refers to low birth weight.
Answer Key
About Leave-One-Out Cross-Validation (LOOCV) in Clinical Prediction LOOCV is a rigorous way to test how well a predictive model generalizes to unseen patient data.
Think of your data as a cohort of patients: In the birthwt dataset, you have records for 189 mothers and their newborns, where each row represents a clinical case containing maternal attributes (age, weight) and the birth weight outcome (low).
Leave one patient out at a time: In LOOCV, you set aside one patient’s record as your “test” data.
Train on the remaining cohort: The remaining 188 patients become your “training” data to fit the logistic regression model.
Iterate across the cohort: You repeat this process 189 times—once for every patient—so that every single patient serves as the test case exactly once.
- Q2: Please use the first 188 rows as training data and the 189th row as testing data. Please implement the
train_n_predict(train_data, test_data)function which use train_data to make a linear regressionlow ~ age + lwt + ptd + ht, and return the prediction results on the test_data.
Hint: As Low and High is a dichotomous outcome. You need to use a suitable regression methods
Answer Key
Answer Key
Q3.
Now, we need to do this for a total of 189 times:
For the first time, take out the first row as test data and use the rest of the 188 rows as training data.
For the second time, take out the second row as test data and use the rest of the 188 rows as training data.
And so on, for all 189 entries.
and remember to store the test result in data$predict (i.e., if the test data is the 1st row of the data, then data$predict[1] <- train_n_predict(data[-1,], data[1,])).
Answer Key
- Q4: After getting the predicted probability, we need to convert it into a clinical classification. The function
train_n_predictgives the probability that the infant has a low birth weight (low = 1). Therefore, ifdata$predict > 0.5, we can classify the case as low birth weight, and ifdata$predict < 0.5, we classify it as normal weight.
Based on this idea, create a new column data$p_class with factor data type, where if data$predict >= 0.5 it shall be low (original label for low birth weight) and normal if data$predict < 0.5.
Answer Key
Alternatively, loop can tackle the problem as well as below
Using for loops for data frame row-by-row manipulation in R is generally not recommended (and is considered an anti-pattern). Because data frames in R are underlying lists of vectors, growing them dynamically or modifying elements one-by-one inside a loop causes R to frequently reallocate memory in the background, leading to severe performance bottlenecks on larger datasets. Vectorized functions (like ifelse(), dplyr::case_when(), or logical vector indexing with factor levels) are significantly faster, more memory-efficient, and easier to read.
- Q5: Now that we have classified our predictions (data\(p_class) and have the actual clinical outcomes (data\)low), we want to see which predictions were correct.
Please create a new logical column named data$correct using a logical comparison (==). It should evaluate to TRUE if the predicted classification matches the actual birth weight status, and FALSE otherwise.
Answer Key
- Q6: Model accuracy is defined as the proportion of correct predictions out of the total number of cases.
Using your logical comparison or the correct column you just created, calculate the overall prediction accuracy of your Leave-One-Out Cross-Validation (LOOCV) model. (Hint: In R, taking the mean() of a logical vector treats TRUE as 1 and FALSE as 0, giving you the exact proportion of correct values).
Answer Key
Question Set 3
Let’s go back to the question in the tutorial 1 this time you need implement a function to solve a quadratic equation and return “There is no real roots for this quadratic equation” whenever appropriate.
\[ ax^2+bx+c=0 \]
Question Set 4
This question set is adapted from the NIH Bioinformatics Training and Education Program. The original question is slightly more complex. If you are interested in more challenging questions, you can visit the website.
Let’s load the Titanic dataset.
| Column | Description |
|---|---|
| Survived | 0 (No) / 1 (Yes) |
| Pclass | 1 / 2 / 3 (Passenger Class) |
| Name | Passenger Name |
| Sex | Male / Female |
| Age | Age |
| Siblings.Spouses.Aboard | Number of siblings/spouses aboard |
| Parents.Children.Aboard | Number of parents/children aboard |
| Fare | Fare Price |
- Q1: Inspect the data using
str(),summary(), andhead().
Answer Key
- Q2: Explore the relationship between the passenger’s age and fare. What type of plot should you use? Write the code using
ggplot2.
Answer Key A scatter plot:
- Q3: Color the points from Q2 by
Pclass. Remember thatPclassis a proxy for socioeconomic status. While the values are treated as numeric upon loading, they are categorical and should be treated as such. You will need to coercePclassinto a categorical (factor) variable usingfactor()oras.factor().
Answer Key
- Q4: Modify the plot from Q3 to update the legend labels to (1 = 1st Class, 2 = 2nd Class, 3 = 3rd Class).
Answer Key