3: Control Flow, Logic & Functions in R
Tested Stacks:
GATK 4.6.1
Samtools 1.21
Nextflow 24.10
Seurat v5.1
Python 3.12
Prerequisites: Basic Linux CLI & Sequencing Formats
📚 Chapter 3 of 13
0% Course Completed
Chapter 3: Control Flow, Logic & Functions in R
While standard procedural scripts use explicit loops, idiomatic R prioritizes vectorization and functional programming (the apply family). Mastering vectorized logic speeds up genome-wide computations by orders of magnitude.
1. Vectorized Conditionals with ifelse()
Classifying Phred quality scores across sequencing bases in a single vectorized pass:
phred_scores <- c(38, 22, 14, 40, 28, 35, 18, 33)
quality_tier <- ifelse(phred_scores >= 30, "Q30+ (High Accuracy, <= 0.1% error)",
ifelse(phred_scores >= 20, "Q20+ (Acceptable, <= 1.0% error)",
"Low Quality (Needs Trimming)"))
for (i in seq_along(phred_scores)) {
cat(sprintf("Base %d [Q%02d]: %s\n", i, phred_scores[i], quality_tier[i]))
}2. Functional Programming: The Apply Family in Genomics
Operating across rows (genes) or columns (samples) in count matrices without manual loops:
# Calculate gene variance across 100 samples
gene_vars <- apply(counts_matrix, 1, var)
# Calculate sample median read counts
sample_medians <- apply(counts_matrix, 2, median)
# Normalize sample columns with sweep
size_factors <- c(1.1, 0.95)
norm_counts <- sweep(counts_matrix, 2, size_factors, "/")3. Custom Bioinformatics Functions: Genetic Code Translator
Building reusable functions with input validation:
translate_dna <- function(dna_sequence, to_stop = TRUE) {
codon_map <- c(
"TTT"="F", "TTC"="F", "TTA"="L", "TTG"="L",
"TCT"="S", "TCC"="S", "TCA"="S", "TCG"="S",
"TAT"="Y", "TAC"="Y", "TAA"="*", "TAG"="*",
"TGT"="C", "TGC"="C", "TGA"="*", "TGG"="W",
"CTT"="L", "CTC"="L", "CTA"="L", "CTG"="L",
"ATG"="M", "ACT"="T", "AAT"="N", "AAA"="K",
"GTT"="V", "GCT"="A", "GAT"="D", "GGA"="G"
)
seq_clean <- toupper(gsub("[^ACGT]", "", dna_sequence))
n <- nchar(seq_clean)
num_codons <- floor(n / 3)
codons <- substring(seq_clean, seq(1, by = 3, length.out = num_codons),
seq(3, by = 3, length.out = num_codons))
aa <- character(num_codons)
for (i in seq_along(codons)) {
res <- codon_map[codons[i]]
if (is.na(res)) res <- "X"
if (to_stop && res == "*") break
aa[i] <- res
}
paste(aa[aa != ""], collapse = "")
}
cat("Peptide:", translate_dna("ATGGCTTTTAAATGA"), "\n")
⚠️
Common Pitfalls & Troubleshooting Checklist
- Java Heap Exhaustion (GATK / Picard): If processes terminate with
java.lang.OutOfMemoryError, set your environment variable explicitly:export _JAVA_OPTIONS="-Xmx16g -Djava.io.tmpdir=/tmp". - Index Timestamp Mismatch: If tools complain that a BAM index is missing or out of date, regenerate with
samtools index -@ 4 sample.bam. - Conda Channel Conflicts: Avoid ABI incompatibilities between bioconda and conda-forge by setting strict priority:
conda config --set channel_priority strict. - Chromosome Naming Contamination: Always verify whether reference FASTA headers use
chr1or1; divergent naming causes silent alignment drops.
Was this guide helpful to your research?
Help us maintain 100% accurate, peer-reviewed bioinformatics standards.