R
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Data Structures
-
Section 4: Data Manipulation
-
Section 5: Visualization and Statistics
-
Section 6: Advanced R
-
Section 7: Practical Projects
-
Section 8: Interview Practice
-
Section 9: More Practice Exercises
-
Section 10: Shiny Apps in Depth
-
Section 11: More Data Wrangling
-
Section 12: Tidyverse Deep Dive
-
Section 13: Statistical Modeling Deep Dive
-
Section 14: Machine Learning in R
-
Section 15: R Visualization Deep Dive
-
Section 16: R Package Development Deep Dive
-
Section 17: R for Reproducible Research
-
Section 18: R and Databases
-
Section 19: R Performance Optimization
-
Section 20: Bioinformatics and Specialized R
-
Section 21: More Shiny Practice
-
Section 22: More Practice Exercises
-
Section 23: R Data Structures Deep Dive
-
Section 24: More Interview and Review
-
Section 25: R for Business Analytics
-
Section 26: R Text Mining and NLP
-
Section 27: R Spatial Data Analysis
-
Section 28: R Deep Learning
-
Section 29: Advanced Statistical Techniques
-
Section 30: R Object Systems Deep Dive
-
Section 31: R Environments and Metaprogramming
-
Section 32: R for Finance
-
Section 33: R for Clinical and Health Data
-
Section 34: More Shiny Advanced Practice
-
Section 35: R Data Cleaning Deep Dive
-
Section 36: R Reporting Automation
-
Section 37: More Practical Projects Round 2
-
Section 38: R Ecosystem and Career
-
Section 39: More Visualization Practice
-
Section 40: R for Experimentation
-
Section 41: R for Genomics and Bioinformatics Deep Dive
-
Section 42: R for Marketing Analytics
-
Section 43: R Data Import/Export Deep Dive
-
Section 44: R String Processing Deep Dive
-
Section 45: R for Actuarial and Insurance Analytics
-
Section 46: R Testing and Quality Assurance Deep Dive
-
Section 47: R Version Control and Collaboration
-
Section 48: R Advanced Functional Programming
-
Section 49: R for Supply Chain and Operations
-
Section 50: More Practice Exercises Round 3
-
Section 51: R Dashboards and BI Integration
-
Section 52: R Data Governance and Ethics
-
Section 53: More Modeling Practice
-
Section 54: R Final Capstone Projects
-
Section 55: R for Sports Analytics
-
Section 56: More Interview Practice Round 2
-
Section 57: R Networking and APIs
-
Section 58: R for Environmental Science
-
Section 59: R Notebook and Documentation Practices
-
Section 60: More Data Wrangling Mastery
-
Section 61: R for A/B Testing at Scale
-
Section 62: R Package Ecosystem Deep Dive
163: Working with Genomic Ranges (GRanges)
How do I actually build a GRanges object from scratch?
If you've spent any time in bioinformatics, you know that genomic coordinates are a nightmare to track in a standard data frame. You've got chromosomes, start positions, end positions, and the strand—and if you get one wrong, your whole analysis is garbage. That's why we use GRanges from the GenomicRanges package. It's not just a list; it's a specialized object that understands the "geometry" of a genome.
I usually start by defining my coordinates explicitly. Let's say we're looking at a few specific regions on Chromosome 17, perhaps around the TP53 gene. Here is how I'd set that up:
library(GenomicRanges)
# Let's define some regions of interest
my_ranges <- GRanges(
seqnames = "chr17",
ranges = IRanges(start = c(7661779, 7686769), end = c(7686448, 7686915)),
strand = c("+", "-"),
name = c("region_A", "region_B")
)
my_ranges
Notice that I used IRanges inside the GRanges call. Think of IRanges as the "integer range" (the start and end) and GRanges as the "genomic range" (the integer range + the chromosome + the strand). I've also added a name column. You can add almost any metadata you want here, and it stays glued to the coordinates.
How do I find overlaps between two different genomic datasets?
This is where GRanges really earns its keep. Imagine you have one set of ranges representing your "peaks" from a ChIP-seq experiment and another set representing known gene promoters. You want to know which peaks hit which promoters. In a standard data frame, you'd be writing nested loops or complex joins. In GenomicRanges, you just use findOverlaps.
# Dataset 1: My experimental peaks
peaks <- GRanges(seqnames = "chr17", ranges = IRanges(start = c(7660000, 7670000), end = c(7665000, 7675000)))
# Dataset 2: Known promoter regions
promoters <- GRanges(seqnames = "chr17", ranges = IRanges(start = c(7661000, 7680000), end = c(7662000, 7681000)))
# Find the overlaps
hits <- findOverlaps(peaks, promoters)
# 'hits' is a Hits object, which is basically a mapping of indices.
# To see which peak index matches which promoter index:
hits
The Hits object is incredibly memory efficient, which is vital when you're dealing with millions of reads. If you want to actually extract the overlapping ranges, you can use the hits to subset your objects, like peaks[queryHits(hits)]. I've found that most people struggle with the Hits object at first, but once you realize it's just a map of "Index A matches Index B," it becomes second nature.
What does "reducing" actually do to my ranges?
You'll see the reduce() function everywhere in genomic pipelines. In plain English: reduce takes a set of overlapping or abutting ranges and merges them into a single, larger range. It's basically "collapsing" the intervals.
I often use this when I have a bunch of fragmented reads that I know belong to the same biological feature. I don't care about the individual gaps; I just want the total footprint of the activity.
# Create some overlapping ranges
messy_ranges <- GRanges(
seqnames = "chr17",
ranges = IRanges(start = c(100, 150, 500), end = c(200, 250, 600))
)
# Merge them
clean_ranges <- reduce(messy_ranges)
# messy_ranges had (100-200) and (150-250).
# clean_ranges will have (100-250) and (500-600).
clean_ranges
Just a heads-up: reduce() will merge ranges on the same chromosome and strand. If you have ranges on different strands, they won't be merged even if they overlap perfectly. That's usually what you want, because the strand carries critical biological meaning.
📋 Practical Task
Exercise: Merging and Filtering ChIP-seq Peak Intervals
You have been given a set of raw ChIP-seq peak coordinates on Chromosome 1. Some of these peaks overlap because the peak-calling software was too sensitive. Your goal is to merge these overlapping regions into "consolidated peaks" and then filter out any consolidated peak that is shorter than 200 base pairs (as these are likely noise).
Instructions:
- Create a
GRangesobject calledraw_peakswith the following coordinates on "chr1":- Start: 1000, End: 1200
- Start: 1100, End: 1300
- Start: 5000, End: 5100
- Start: 8000, End: 8500
- Start: 8400, End: 8600
- Use the
reduce()function to merge overlapping intervals into a new object calledmerged_peaks. - Calculate the width of these merged peaks using the
width()function. - Filter
merged_peaksto keep only those with a width ≥ 200. - Print the final filtered
GRangesobject.
There are no comments for now.