Triple-negative breast cancer accounts for approximately 15% of breast cancer cases and lacks ER, PR, and HER2 receptors, Consequently, standard targeted endocrine and anti-HER2 therapies are ineffective, making the discovery of novel biological drivers and therapeutic targets critical for improving patient outcomes.
The goal of this project is to identify drug repurposing candidates for TNBC by integrating differential transcriptomic expression with functional protein networks and open-source drug-target databases.
The primary analysis workflow consists of: - Differential Expression Analysis - Network and Pathway Integration - Translational Drug Matching
data_dir <- "/shared/dreamhigh/data"
For this project I will use:
brca_expr_matbrca_clin.csvbrca_expr_mat <- readRDS(file.path(data_dir, "brca_expr_mat.rds"))
brca_clin_df <- read.csv(file.path(data_dir, "brca_clin.csv"), stringsAsFactors = FALSE)
To isolate the TNBC cohort, clinical samples are categorized based on their receptor status. Samples lacking ER, PR, and HER2 receptors are classified into the TNBC group, while samples with at least one receptor are assigned to the Non-TNBC control group.
is_tnbc <- brca_clin_df$estrogen_receptor_status == "Negative" &
brca_clin_df$progesterone_receptor_status == "Negative" &
brca_clin_df$her2_receptor_status == "Negative"
is_non_tnbc <- brca_clin_df$estrogen_receptor_status == "Positive" |
brca_clin_df$progesterone_receptor_status == "Positive" |
brca_clin_df$her2_receptor_status == "Positive"
brca_clin_df$group <- NA
brca_clin_df$group[is_tnbc] <- "TNBC"
brca_clin_df$group[is_non_tnbc] <- "Non_TNBC"
table(brca_clin_df$group, useNA = "ifany")
##
## Non_TNBC TNBC <NA>
## 851 114 117
After matching sample ids with their groups, I calculated average transcript expression levels across all samples for each gene to establish a baseline for downstream differential expression analysis.
tnbc_id <- brca_clin_df$bcr_patient_barcode[which(brca_clin_df$group == "TNBC")]
non_tnbc_id <- brca_clin_df$bcr_patient_barcode[which(brca_clin_df$group == "Non_TNBC")]
mean_tnbc <- rowMeans(brca_expr_mat[, tnbc_id], na.rm = TRUE)
mean_non_tnbc <- rowMeans(brca_expr_mat[, non_tnbc_id], na.rm = TRUE)
To get a clearer picture and observe the difference between TNBC and the control group, the relative expression change between cohorts is calculated on the log2 scale by subtracting non-TNBC mean expression from TNBC mean expression.
log2_fc <- mean_tnbc - mean_non_tnbc
deg_results <- data.frame(
Gene = rownames(brca_expr_mat),
Mean_TNBC = mean_tnbc,
Mean_Non_TNBC = mean_non_tnbc,
log2FC = log2_fc
)
To evaluate the statistical significance of differential gene expression across cohorts, Welch’s two-sample t-test is performed across all rows of the matrix. Raw p-values must be adjusted for multiple hypothesis testing using the Benjamini-Hochberg false discovery rate correction procedure to ensure that the data is statistically significant. Finally, I sorted the results by applying these filters adjusted p-value < 0.05 (statistical significance) and Log2 fold-change > 1.5 (biological significance).
raw_p_values <- apply(brca_expr_mat, 1, function(gene_expr) {
t.test(gene_expr[tnbc_id], gene_expr[non_tnbc_id])$p.value
})
p_adj <- p.adjust(raw_p_values, method = "BH")
deg_results$pvalue <- raw_p_values
deg_results$padj <- p_adj
deg_results <- deg_results[order(-deg_results$log2FC), ]
significant_genes <- subset(deg_results, p_adj < 0.05 & log2FC > 1.5)
write.csv(significant_genes, "TNBC_Significant_Genes.csv", row.names = FALSE)
nrow(significant_genes)
## [1] 468
head(significant_genes, 15)
## Gene Mean_TNBC Mean_Non_TNBC log2FC pvalue padj
## VGLL1 VGLL1 8.196639 2.663462 5.533177 1.925963e-36 1.368106e-34
## GABRP GABRP 12.058556 7.051977 5.006580 2.111348e-28 5.898579e-27
## FABP7 FABP7 7.652141 2.667936 4.984205 3.171768e-28 8.741202e-27
## ART3 ART3 6.348351 1.420819 4.927532 1.452655e-29 4.614005e-28
## A2ML1 A2ML1 7.432452 2.515493 4.916960 1.114162e-33 5.751898e-32
## KRT16 KRT16 9.896110 5.302280 4.593829 9.618574e-30 3.147850e-28
## PRAME PRAME 8.365796 4.058335 4.307461 8.770880e-26 1.749627e-24
## PPP1R14C PPP1R14C 8.482416 4.261234 4.221182 1.256442e-44 2.132846e-42
## ZIC1 ZIC1 6.638624 2.425623 4.213000 8.243553e-30 2.712381e-28
## SOX10 SOX10 9.143958 4.984038 4.159919 1.208994e-18 1.114549e-17
## ELF5 ELF5 9.951660 5.801629 4.150030 1.673393e-27 4.224279e-26
## UGT8 UGT8 7.467442 3.349684 4.117758 5.254620e-36 3.553558e-34
## PSAT1 PSAT1 9.798664 5.737591 4.061073 2.246703e-53 8.578194e-51
## MIA MIA 8.211815 4.228309 3.983506 1.088737e-25 2.147824e-24
## TTYH1 TTYH1 8.032283 4.102711 3.929572 8.287096e-24 1.317239e-22
After applying the filters mentioned above, over 400 genes were left to evaluate. I made a list of top 15 and top 100 most significant genes, which I will use later to perform analyses and identify targets.
top15_genes <- head(significant_genes, 15)
write.csv(top15_genes, "TNBC_Top15_Targets.csv", row.names = FALSE)
write.table(
head(significant_genes$Gene, 100),
file = "top100_genes.txt",
row.names = FALSE,
col.names = FALSE,
quote = FALSE
)
Data visualization plays a critical role in revealing underlying patterns, distribution trends, and structural relationships within transcriptomic datasets.
To better visualize how distinctly our top candidate genes separate TNBC from non-TNBC tumors, I plotted an expression heatmap using 30 representative samples (15 TNBC and 15 non-TNBC). I standardized the expression levels across the genes so that relative over-expression appears in red and under-expression appears in blue, making it easy to observe how consistently these targets are elevated in the TNBC cohort.
set.seed(42)
sub_tnbc <- sample(tnbc_id, 15)
sub_non_tnbc <- sample(non_tnbc_id, 15)
sub_samples <- c(sub_tnbc, sub_non_tnbc)
sub_mat <- brca_expr_mat[top15_genes$Gene, sub_samples]
sub_zscore <- t(scale(t(sub_mat)))
col_palette <- colorRampPalette(c("royalblue", "white", "firebrick"))(100)
par(mar = c(5, 6, 4, 2))
image(
1:ncol(sub_zscore), 1:nrow(sub_zscore), t(sub_zscore),
col = col_palette, axes = FALSE, xlab = "", ylab = "",
main = "Expression Heatmap (30 Representative Samples)"
)
axis(2, at = 1:nrow(sub_zscore), labels = rownames(sub_zscore), las = 2, cex.axis = 0.8)
axis(1, at = c(7.5, 22.5), labels = c("TNBC (n=15)", "Non-TNBC (n=15)"), tick = FALSE)
abline(v = 15.5, lwd = 2, lty = 2)
To see the overall landscape of gene expression changes across all genes at once, I generated a volcano plot. I mapped the magnitude of fold change against statistical significance so I could easily highlight which genes are significantly upregulated or downregulated in TNBC, as well as where my top 15 candidate driver genes fall relative to the entire dataset.
deg_results$neg_log10_padj <- -log10(deg_results$padj)
top_genes_vector <- top15_genes$Gene
is_top_candidate <- rownames(deg_results) %in% top_genes_vector
deg_results$group <- "Not significant"
deg_results$group[deg_results$padj < 0.05 & deg_results$log2FC > 1.5] <- "Upregulated in TNBC"
deg_results$group[deg_results$padj < 0.05 & deg_results$log2FC < -1.5] <- "Downregulated in TNBC"
deg_results$group[rownames(deg_results) %in% top15_genes] <- "Top candidate drivers"
plot_colors <- c(
"Not significant" = "gray70",
"Upregulated in TNBC" = "firebrick",
"Downregulated in TNBC" = "royalblue",
"Top candidate drivers" = "purple"
)
bg_data <- deg_results[!is_top_candidate, ]
plot(
deg_results$log2FC,
deg_results$neg_log10_padj,
pch = 16,
cex = 0.5,
col = plot_colors[deg_results$group],
xlab = "Log2 Fold Change (TNBC vs Non-TNBC)",
ylab = "-Log10(Adjusted p-value)",
main = "Volcano Plot of Differential Gene Expression"
)
top_data <- deg_results[is_top_candidate, ]
points(
top_data$log2FC,
top_data$neg_log10_padj,
pch = 19,
cex = 1.1,
col = "purple"
)
abline(v = 0, lwd = 2)
abline(v = c(-1.5, 1.5), lty = 2)
abline(h = -log10(0.05), lty = 2)
legend(
"topright",
legend = names(plot_colors),
col = plot_colors,
pch = 16,
cex = 0.8,
bty = "n"
)
Using the top 100 significantly upregulated genes, I performed functional enrichment via Enrichr (KEGG 2026 and WikiPathways 2024 Human). Only pathways meeting strict statistical significance criteria (p_adj < 0.05) were included:
Enrichr Pathway Results
Enrichr Pathway Results
To uncover the biological processes driven by my candidate genes, I performed pathway enrichment analysis and plotted the top results. By graphing the pathways against their statistical significance, I highlighted the primary biological mechanisms that are most heavily altered in TNBC.
pathway_names <- c(
"IL-17 Signaling Pathway",
"Cornified Envelope Formation",
"Pancreatic Cancer Subtypes",
"Glucocorticoid Receptor Pathway",
"Oligodendrocyte Differentiation",
"Nuclear Receptors Meta Pathway"
)
padj_values <- c(1.2e-6, 3.4e-5, 2.1e-4, 1.5e-3, 4.2e-3, 8.1e-3)
neg_log10_padj <- -log10(padj_values)
scores <- rev(neg_log10_padj)
labels <- rev(pathway_names)
par(mar = c(5, 16, 4, 2))
barplot(
scores,
names.arg = labels,
horiz = TRUE,
las = 1,
col = "firebrick",
border = NA,
xlab = "-Log10(Adjusted p-value",
main = "Top Enriched Biological Pathways"
)
par(mar = c(5, 4, 4, 2) + 0.1)
I performed drug-gene interaction screening via DGIdb to asses targetability and drug repurposing potential, using the top 15 candidate genes:
DGIdb Results
To determine how the top 15 most upregulated genes are connected to each other and the network hierarchy, I performed protein-protein interaction (PPI) analysis in STRING-DB.
my_cap <- "STRING-DB Protein-Protein Interaction Network of Top 15 Candidate Genes."
knitr::include_graphics("ppi.png")
STRING-DB Protein-Protein Interaction Network of Top 15 Candidate Genes.
As shown in the network mapping above, SOX10 and FABP7 emerge as central interconnected hubs within our candidate set, linking key targets like ZIC1, TTYH1, and MIA.
drug_info <- read.delim("repurposing_drugs.txt", comment.char = "!", check.names = FALSE)
pattern <- paste(top15_genes$Gene, collapse = "|")
matched_rows <- grep(pattern, drug_info$target, ignore.case = TRUE)
matched_drugs <- drug_info[matched_rows, ]
matched_drugs[, c("pert_iname", "target", "moa", "clinical_phase", "indication")]
## pert_iname
## 289 acamprosate
## 594 amoxapine
## 1343 butalbital
## 2144 dehydroepiandrosterone
## 2561 enflurane
## 2728 etomidate
## 2903 flumazenil
## 3326 halothane
## 3648 isoflurane
## 3965 L-glutamic-acid
## 4219 MC-1
## 4346 metharbital
## 4361 methoxyflurane
## 4994 olanzapine
## 5636 primidone
## 5682 propofol
## 6288 sevoflurane
## 6983 topiramate
## target
## 289 GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GRIN1 | GRIN2A | GRIN2B | GRIN2C | GRIN2D | GRIN3A | GRIN3B | GRM5
## 594 ADRA1A | ADRA1B | ADRA1D | ADRA2A | ADRA2B | ADRA2C | CHRM1 | CHRM2 | CHRM3 | CHRM4 | CHRM5 | DRD1 | DRD2 | DRD3 | DRD4 | DRD5 | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | HRH1 | HRH4 | HTR1A | HTR1B | HTR2A | HTR2B | HTR2C | HTR3A | HTR6 | HTR7 | SLC6A2 | SLC6A3 | SLC6A4
## 1343 CHRNA4 | CHRNA7 | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GRIA2 | GRIK2
## 2144 AR | CYP3A5 | ESR1 | ESR2 | G6PD | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GRIN1 | GRIN2A | GRIN2B | GRIN2C | GRIN2D | GRIN3A | GRIN3B | HSD17B1 | NR1I2 | NR1I3 | PPARA | SIGMAR1 | SULT2A1 | SULT2B1
## 2561 CYP2E1 | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GLRA1 | GLRB | KCNK10 | KCNK18 | KCNK2 | KCNK3 | KCNK9
## 2728 ADRA2B | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ
## 2903 GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ
## 3326 CYP2E1 | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GLRA1 | GLRB | KCNK10 | KCNK12 | KCNK13 | KCNK15 | KCNK18 | KCNK2 | KCNK3 | KCNK9
## 3648 GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GLRA1 | GLRB | KCNK10 | KCNK18 | KCNK2 | KCNK3 | KCNK9
## 3965 AADAT | AASS | ABAT | ALDH18A1 | ASNS | BCAT1 | BCAT2 | CCBL2 | DNPEP | EARS2 | ENPEP | EPRS | FOLH1 | FPGS | FTCD | GAD1 | GAD2 | GATB | GCLC | GCLM | GGCX | GLS | GLS2 | GLUD1 | GLUD2 | GLUL | GMPS | GOT1 | GOT2 | GPT | GPT2 | GRIA1 | GRIA2 | GRIA3 | GRIA4 | GRID1 | GRID2 | GRIK1 | GRIK2 | GRIK3 | GRIK4 | GRIK5 | GRIN1 | GRIN2A | GRIN2B | GRIN2C | GRIN2D | GRIN3A | GRIN3B | GRM1 | GRM2 | GRM3 | GRM4 | GRM6 | GRM7 | GRM8 | LGSN | NADSYN1 | NAGS | OPLAH | PFAS | PGCP | PSAT1 | SLC1A1 | SLC1A2 | SLC1A3 | SLC1A6 | SLC1A7 | SLC25A18 | SLC25A22 | SLC7A11 | TAT
## 4219 AADAT | ABAT | AGXT | AGXT2 | ALAS1 | AZIN2 | BCAT1 | BCAT2 | CBS | CCBL1 | CCBL2 | CSAD | CTH | DDC | FTCD | GAD1 | GAD2 | GADL1 | GCAT | GLDC | GOT1 | GOT2 | GPT | GPT2 | HDC | IGSF10 | KYNU | MOCOS | NFS1 | OAT | ODC1 | PDXDC1 | PDXP | PHYKPL | PNPO | PROSC | PSAT1 | PYGB | PYGL | PYGM | SCLY | SDS | SDSL | SEPSECS | SGPL1 | SHMT1 | SHMT2 | SPTLC1 | SPTLC2 | SPTLC3 | SRR | TAT | THNSL1
## 4346 CHRNA4 | CHRNA7 | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GRIA2 | GRIK2
## 4361 ATP2C1 | ATP5D | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GLRA1 | GLRB | GRIA1 | KCNA1 | MT-ND1
## 4994 ADRA1A | ADRA1B | ADRA2A | ADRA2B | ADRA2C | ADRB1 | ADRB2 | ADRB3 | CHRM1 | CHRM2 | CHRM3 | CHRM4 | CHRM5 | CYP2C8 | DRD1 | DRD2 | DRD3 | DRD4 | DRD5 | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | HRH1 | HRH2 | HRH4 | HTR1A | HTR1B | HTR1D | HTR1E | HTR1F | HTR2A | HTR2B | HTR2C | HTR3A | HTR5A | HTR6 | HTR7
## 5636 CHRNA4 | CHRNA7 | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GRIA2 | GRIK2 | SCN10A | SCN11A | SCN1A | SCN2A | SCN3A | SCN4A | SCN5A | SCN7A | SCN8A | SCN9A
## 5682 CYP2B6 | FAAH | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | SCN2A | SCN4A | TRPV1
## 6288 ATP2C1 | ATP5D | CYP2E1 | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GLRA1 | GLRB | GRIA1 | KCNA1 | KCNK10 | KCNK18 | KCNK2 | KCNK3 | KCNK9 | MT-ND1
## 6983 CA1 | CA12 | CA2 | CA4 | CA7 | CYP2C19 | CYP3A4 | GABRA1 | GABRA2 | GABRA3 | GABRA4 | GABRA5 | GABRA6 | GABRB1 | GABRB2 | GABRB3 | GABRD | GABRE | GABRG1 | GABRG2 | GABRG3 | GABRP | GABRQ | GRIA1 | GRIA2 | GRIA3 | GRIA4 | GRIK1 | GRIK2 | GRIK3 | GRIK4 | GRIK5 | SCN10A | SCN11A | SCN1A | SCN2A | SCN3A | SCN4A | SCN5A | SCN7A | SCN8A | SCN9A
## moa
## 289 glutamate receptor antagonist
## 594 norepinephrine reputake inhibitor
## 1343 GABA receptor antagonist
## 2144 protein synthesis stimulant
## 2561 membrane permeability inhibitor
## 2728 GABA receptor modulator
## 2903 benzodiazepine receptor antagonist
## 3326 glutamate receptor antagonist
## 3648 inhaled anaesthetic
## 3965 glutamate receptor agonist
## 4219
## 4346 GABA receptor modulator
## 4361 membrane permeability inhibitor
## 4994 dopamine receptor antagonist | serotonin receptor antagonist
## 5636 GABA receptor antagonist
## 5682 benzodiazepine receptor agonist
## 6288 membrane integrity inhibitor
## 6983 carbonic anhydrase inhibitor | glutamate receptor antagonist | kainate receptor antagonist
## clinical_phase indication
## 289 Launched abstinence from alcohol
## 594 Launched depression
## 1343 Launched headache | muscle relaxant
## 2144 Launched menopause
## 2561 Launched anesthetic
## 2728 Launched general anaesthetic
## 2903 Launched sedative
## 3326 Launched general anaesthetic
## 3648 Launched general anaesthetic
## 3965 Launched
## 4219 Phase 3
## 4346 Launched epilepsy
## 4361 Launched general anaesthetic
## 4994 Launched bipolar disorder | schizophrenia
## 5636 Launched seizures
## 5682 Launched anesthetic
## 6288 Launched anesthetic
## 6983 Launched epilepsy | migraine headache
Mapping the top overexpressed candidate genes against the Broad Institute Drug Repurposing Hub yielded 18 compound matches (as seen on the table). The concentration of launched GABA receptor modulators highlights GABRP-mediated signaling as a distinct therapeutic target in this subtype.
I built a computational pipeline in R to find drug repurposing candidates for Triple-Negative Breast Cancer across three main phases:
Cross-referencing our candidates against the Broad Institute Drug Repurposing Hub yielded 18 matching compounds:
```