Loops are fundamental programming constructs that allow us to execute code repeatedly. In pharmaceutical data science and research using R, loops are essential for processing clinical trial data, analyzing drug interactions, calculating pharmacokinetic parameters, and automating repetitive analytical tasks.
11.1 Types of Loops in R
11.1.1 1. For Loops
For loops iterate over a sequence of items for a predetermined number of times.
11.1.1.1 Basic Syntax (R)
for (variable in sequence) {# code to execute}
11.1.1.2 Example 1: Processing Patient Data
# Patient IDs in a clinical trialpatient_ids <-c("PT001", "PT002", "PT003", "PT004", "PT005")# Processing each patientfor (patient_id in patient_ids) {cat("Processing data for patient:", patient_id, "\n")# Simulate data processingcat(" - Vital signs checked\n")cat(" - Adverse events recorded\n")cat(" - Drug concentration measured\n")cat("\n")}
Processing data for patient: PT001
- Vital signs checked
- Adverse events recorded
- Drug concentration measured
Processing data for patient: PT002
- Vital signs checked
- Adverse events recorded
- Drug concentration measured
Processing data for patient: PT003
- Vital signs checked
- Adverse events recorded
- Drug concentration measured
Processing data for patient: PT004
- Vital signs checked
- Adverse events recorded
- Drug concentration measured
Processing data for patient: PT005
- Vital signs checked
- Adverse events recorded
- Drug concentration measured
11.1.1.3 Example 2: Drug Dosage Calculations
# Different patient weights (kg)patient_weights <-c(65, 72, 58, 80, 95, 68)# Drug dosage: 5 mg/kgdose_per_kg <-5cat("Patient Dosage Calculations:\n")
Patient Dosage Calculations:
cat(strrep("-", 40), "\n")
----------------------------------------
for (i inseq_along(patient_weights)) { weight <- patient_weights[i] dosage <- weight * dose_per_kgcat(sprintf("Patient %d: %dkg → %dmg\n", i, weight, dosage))}
while (current_concentration < target_concentration && day <=14) {cat(sprintf("Day %d:\n", day))cat(sprintf(" Current dose: %. 1fmg\n", current_dose))cat(sprintf(" Current concentration: %.1fmg/L\n", current_concentration))# Increase dose by 20% if below targetif (current_concentration < target_concentration) { current_dose <- current_dose *1.2# Simulate concentration response current_concentration <- (current_dose * bioavailability) / volume_distribution } day <- day +1}
Day 1:
Current dose: %.0 1fmg
Current concentration: 8.0mg/L
Day 2:
Current dose: %.0 1fmg
Current concentration: 1.9mg/L
Day 3:
Current dose: %.0 1fmg
Current concentration: 2.3mg/L
Day 4:
Current dose: %.0 1fmg
Current concentration: 2.8mg/L
Day 5:
Current dose: %.0 1fmg
Current concentration: 3.3mg/L
Day 6:
Current dose: %.0 1fmg
Current concentration: 4.0mg/L
Day 7:
Current dose: %.0 1fmg
Current concentration: 4.8mg/L
Day 8:
Current dose: %.0 1fmg
Current concentration: 5.7mg/L
Day 9:
Current dose: %.0 1fmg
Current concentration: 6.9mg/L
Day 10:
Current dose: %.0 1fmg
Current concentration: 8.3mg/L
Day 11:
Current dose: %.0 1fmg
Current concentration: 9.9mg/L
Day 12:
Current dose: %.0 1fmg
Current concentration: 11.9mg/L
Day 13:
Current dose: %.0 1fmg
Current concentration: 14.3mg/L
Day 14:
Current dose: %.0 1fmg
Current concentration: 17.1mg/L
# Set seed for reproducible resultsset.seed(123)# Quality control for drug batchbatch_size <-1000tested_units <-0defective_units <-0max_defects_allowed <-5# 0. 5% defect ratecat("Quality Control Testing:\n")
# Find severe interactionscat("\nSevere Drug Interactions:\n")
Severe Drug Interactions:
cat(strrep("-", 30), "\n")
------------------------------
for (i in1:length(drugs)) {for (j in (i+1):length(drugs)) { # Avoid duplicatesif (j <=length(drugs) && interaction_matrix[i, j] ==3) {cat(sprintf("⚠️ %s + %s: SEVERE\n", drugs[i], drugs[j])) } }}
⚠️ Aspirin + Warfarin: SEVERE
11.1.4 4. Loop Control Statements
11.1.4.1 Break Statement
Exits the loop prematurely when a condition is met.
# Finding the first patient with severe adverse eventpatients_data <-data.frame(id =c("PT001", "PT002", "PT003", "PT004", "PT005"),severity =c("Mild", "Moderate", "Severe", "Mild", "Severe"),stringsAsFactors =FALSE)cat("Searching for first severe adverse event:\n")
Searching for first severe adverse event:
for (i in1:nrow(patients_data)) { patient <- patients_data[i, ]cat(sprintf("Checking patient %s: %s\n", patient$id, patient$severity))if (patient$severity =="Severe") {cat(sprintf("⚠️ ALERT: First severe AE found in patient %s\n", patient$id))break# Exit loop immediately }}
Checking patient PT001: Mild
Checking patient PT002: Moderate
Checking patient PT003: Severe
⚠️ ALERT: First severe AE found in patient PT003
11.1.4.2 Next Statement (R equivalent of continue)
Skips the current iteration and moves to the next one.
# Processing only patients with complete datapatients_lab_values <-data.frame(id =c("PT001", "PT002", "PT003", "PT004", "PT005"),creatinine =c(1.2, NA, 0.9, 1.1, 1.3),alt =c(25, 30, NA, 28, 35),stringsAsFactors =FALSE)cat("Processing patients with complete lab data:\n")
Processing patients with complete lab data:
cat(strrep("-", 45), "\n")
---------------------------------------------
for (i in1:nrow(patients_lab_values)) { patient <- patients_lab_values[i, ]# Skip patients with missing dataif (is.na(patient$creatinine) ||is.na(patient$alt)) {cat(sprintf("%s: Skipping - incomplete data\n", patient$id))next# Skip to next iteration }# Process patient with complete data creat <- patient$creatinine alt <- patient$alt# Calculate estimated GFR (simplified formula) egfr <-175* (creat^(-1.154)) # Simplified calculationcat(sprintf("%s: Creatinine=%.1f, ALT=%.0f, eGFR=%.1f\n", patient$id, creat, alt, egfr))# Check for abnormal valuesif (creat >1.2) {cat(" ⚠️ Elevated creatinine\n") }if (alt >40) {cat(" ⚠️ Elevated ALT\n") }}
# Base doses for different age groupspatient_ages <-c(25, 45, 65, 75, 85)base_dose <-100# mg# Function for age-adjusted dosingadjust_dose <-function(age, base_dose =100) {if (age >65) {# Reduce by 1% for every year over 65 adjustment_factor <-1- (age -65) *0.01return(base_dose * adjustment_factor) } else {return(base_dose) }}# Calculate adjusted doses using sapplyadjusted_doses <-sapply(patient_ages, adjust_dose, base_dose = base_dose)cat("Age-Adjusted Dosing:\n")
Age-Adjusted Dosing:
cat(strrep("-", 25), "\n")
-------------------------
for (i inseq_along(patient_ages)) { age <- patient_ages[i] base <- base_dose adjusted <- adjusted_doses[i] adjustment <- ((adjusted - base) / base) *100cat(sprintf("Age %d: %dmg → %. 1fmg (%+.1f%%)\n", age, base, adjusted, adjustment))}
Age 25: 100mg → %.0 1fmg (+0.0%)
Age 45: 100mg → %.0 1fmg (+0.0%)
Age 65: 100mg → %.0 1fmg (+0.0%)
Age 75: 100mg → %.0 1fmg (-10.0%)
Age 85: 100mg → %.0 1fmg (-20.0%)
11.2 Advanced Loop Patterns in R Programming
11.2.1 1. Data Validation with Comprehensive Checks
if (nrow(validation_result$valid_patients) >0) {cat("\nValid Patients:\n")print(validation_result$valid_patients)}
Valid Patients:
id age weight height
1 PT001 45 70 1.75
11.2.2 2. Pharmacokinetic Simulation with Loops
simulate_drug_concentration <-function(dose, ka, ke, vd, time_points) {# Simulate drug concentration over time using one-compartment model# dose: dose in mg# ka: absorption rate constant (1/h)# ke: elimination rate constant (1/h)# vd: volume of distribution (L) concentrations <-numeric(length(time_points))for (i inseq_along(time_points)) { t <- time_points[i]if (ka != ke) {# One-compartment model with first-order absorption conc <- (dose/vd) * (ka/(ka-ke)) * (exp(-ke*t) -exp(-ka*t)) } else {# Special case when ka = ke conc <- (dose/vd) * ka * t *exp(-ke*t) } concentrations[i] <-max(0, conc) # Concentration can't be negative }return(concentrations)}# Simulation parametersdose <-500# mgka <-1.5# absorption rate (1/h)ke <-0.2# elimination rate (1/h)vd <-50# volume of distribution (L)time_points <-seq(0, 24, by =0.5) # 0 to 24 hours, every 0.5hconcentrations <-simulate_drug_concentration(dose, ka, ke, vd, time_points)cat("Pharmacokinetic Simulation:\n")
# Print concentration at key time pointskey_times <-c(0, 0.5, 1, 2, 4, 8, 12, 24)cat("\nConcentration at key time points:\n")
Concentration at key time points:
for (t in key_times) {# Find closest time point closest_idx <-which.min(abs(time_points - t)) actual_time <- time_points[closest_idx] conc <- concentrations[closest_idx]cat(sprintf("T = %4.1fh: %6.2f mg/L\n", actual_time, conc))}
T = 0.0h: 0.00 mg/L
T = 0.5h: 4.99 mg/L
T = 1.0h: 6.87 mg/L
T = 2.0h: 7.16 mg/L
T = 4.0h: 5.16 mg/L
T = 8.0h: 2.33 mg/L
T = 12.0h: 1.05 mg/L
T = 24.0h: 0.09 mg/L
11.2.3 3. Clinical Trial Enrollment Simulation
# Set seed for reproducibilityset.seed(456)simulate_trial_enrollment <-function(target_enrollment, sites, max_weeks =52) {# Initialize tracking variables total_enrolled <-0 week <-0 enrollment_log <-data.frame(week =integer(0),site =character(0),patients_enrolled =integer(0),cumulative_enrolled =integer(0),stringsAsFactors =FALSE )cat("Clinical Trial Enrollment Simulation\n")cat(strrep("=", 40), "\n")cat(sprintf("Target enrollment: %d patients\n", target_enrollment))cat(sprintf("Number of sites: %d\n", length(sites)))cat("\n")while (total_enrolled < target_enrollment && week < max_weeks) { week <- week +1 week_enrolled <-0# Each site attempts to enroll patientsfor (site innames(sites)) {# Random enrollment based on site capacity site_capacity <- sites[[site]] enrolled_this_week <-rpois(1, lambda = site_capacity)if (enrolled_this_week >0) { total_enrolled <- total_enrolled + enrolled_this_week week_enrolled <- week_enrolled + enrolled_this_week# Log the enrollment new_row <-data.frame(week = week,site = site,patients_enrolled = enrolled_this_week,cumulative_enrolled = total_enrolled,stringsAsFactors =FALSE ) enrollment_log <-rbind(enrollment_log, new_row)# Stop if target reachedif (total_enrolled >= target_enrollment) {break } } }# Report progress every 4 weeksif (week %%4==0) {cat(sprintf("Week %d: %d patients enrolled (Total: %d/%.0f%%)\n", week, week_enrolled, total_enrolled, (total_enrolled/target_enrollment)*100)) } }cat("\n")if (total_enrolled >= target_enrollment) {cat(sprintf("✅ Target enrollment reached in week %d!\n", week)) } else {cat(sprintf("⚠️ Enrollment incomplete after %d weeks (%d/%d patients)\n", max_weeks, total_enrolled, target_enrollment)) }return(enrollment_log)}# Define sites with their enrollment capacity (patients per week on average)trial_sites <-list("Site_A"=2.5, # Academic medical center"Site_B"=1.8, # Community hospital"Site_C"=3.1, # Large clinical research center"Site_D"=1.2, # Small clinic"Site_E"=2.0# Regional hospital)# Run simulationenrollment_log <-simulate_trial_enrollment(target_enrollment =100,sites = trial_sites,max_weeks =30)
Remember that efficient loop design and choosing the right approach (loops vs vectorization vs apply functions) can significantly impact the performance and reliability of pharmaceutical data analysis systems in R.