| Title: | Create Volcano Plots for Differential Gene Expression Data |
|---|---|
| Description: | Creates customizable volcano plots for differential gene expression results from RNA-seq analyses. Accepts result objects or tables from 'DESeq2', 'edgeR', and 'limma' directly, with automatic column detection. Labels the most significant or chosen genes, colors gene sets, compares several contrasts side by side, offers colorblind-safe color presets, and can produce interactive plots with 'ggiraph'. Gene tables are rendered with 'gt' and composed with 'patchwork'. |
| Authors: | Loukas Theodosiou [aut, cre] (ORCID: <https://orcid.org/0000-0001-6418-4652>) |
| Maintainer: | Loukas Theodosiou <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.4.0 |
| Built: | 2026-11-01 16:20:08 UTC |
| Source: | https://github.com/cran/ggvolc |
A dataset containing gene expression analysis results. It has seven columns capturing various statistics related to gene expression.
all_genesall_genes
A data frame with the following columns:
Character. Gene name or identifier.
Numeric. The base mean value for the gene across samples.
Numeric. The log2 fold change of gene expression. Positive values indicate upregulation and negative values indicate downregulation.
Numeric. Standard error of the log2 fold change.
Numeric. The Wald statistic for the gene's expression change.
Numeric. Raw p-value for the test of the gene's expression change.
Numeric. Adjusted p-value for multiple testing corrections.
A dataset containing specific genes of interest referred to as "attention genes".
attention_genesattention_genes
A data frame with 10 rows and 7 variables:
Character. Gene name or identifier.
Numeric vector: Base mean expression level of genes
Numeric vector: Log2 Fold Change of gene expression
Numeric vector: Standard error for log2 fold change
Numeric vector: Wald statistic for the gene's expression change
Numeric vector: Raw p-value from Wald test
Numeric vector: Adjusted p-value for multiple testing using the Benjamini-Hochberg procedure
Converts the result objects returned by the three major differential
expression pipelines into a plain data.frame that ggvolc
and genes_table understand. You rarely need to call this
yourself: both functions call it internally, so you can pass the objects
straight in. It is exported for when you want to inspect or filter the
table first.
de_table(x, coef = NULL)de_table(x, coef = NULL)
x |
A DE result object or a data frame (see Details). |
coef |
For a multi-coefficient limma fit, the coefficient (name or
index) to extract. For a |
Supported inputs:
A DESeqResults object from DESeq2::results()
or DESeq2::lfcShrink(), or a DESeqDataSet after
DESeq2::DESeq(), in which case DESeq2::results() is called
for you (with name = coef when coef is given).
A TopTags object from edgeR::topTags(), or a
DGELRT / DGEExact object from edgeR::glmQLFTest(),
edgeR::glmLRT() or edgeR::exactTest(). All genes are kept
(edgeR::topTags(x, n = Inf)).
An MArrayLM fit after limma::eBayes().
limma::topTable(fit, coef = coef, number = Inf) is called for
you. If the fit has more than one coefficient, coef is
required.
Any data.frame (including tibbles) is returned
unchanged.
A data.frame with one row per gene. Gene identifiers are kept
in the row names (or a genes column, if the input had one).
# A data frame passes straight through head(de_table(all_genes)) ## Not run: # DESeq2 dds <- DESeq2::DESeq(dds) ggvolc(DESeq2::results(dds)) # results object ggvolc(dds) # or the dataset itself # edgeR fit <- edgeR::glmQLFit(y, design) ggvolc(edgeR::glmQLFTest(fit, coef = 2)) # limma fit <- limma::eBayes(limma::lmFit(v, design)) ggvolc(fit, coef = "treatment") ## End(Not run)# A data frame passes straight through head(de_table(all_genes)) ## Not run: # DESeq2 dds <- DESeq2::DESeq(dds) ggvolc(DESeq2::results(dds)) # results object ggvolc(dds) # or the dataset itself # edgeR fit <- edgeR::glmQLFit(y, design) ggvolc(edgeR::glmQLFTest(fit, coef = 2)) # limma fit <- limma::eBayes(limma::lmFit(v, design)) ggvolc(fit, coef = "treatment") ## End(Not run)
The same experiment as all_genes, re-expressed with the column
conventions of edgeR's topTags() output. The gene identifiers are
stored in the row names (as topTags() returns them), which lets it
demonstrate that ggvolc accepts edgeR results directly and
promotes rowname gene IDs to a genes column automatically.
edger_genesedger_genes
A data frame with gene identifiers in the row names and the following columns:
Numeric. Log2 fold change of gene expression.
Numeric. Average log2 counts per million.
Numeric. Raw p-value from the differential expression test.
Numeric. Benjamini-Hochberg adjusted p-value (false discovery rate).
Takes a ggplot object (typically from ggvolc) and a data frame
of gene details and produces a combined layout using patchwork.
The gene table is rendered as a polished gt table with color-coded
significance and formatted numeric columns.
genes_table( plot_obj, data2, top_n = NULL, sig_col = c("padj", "pvalue"), dir = c("both", "up", "down", "each"), p_value = 0.05, table_height = NULL, palette = NULL, coef = NULL )genes_table( plot_obj, data2, top_n = NULL, sig_col = c("padj", "pvalue"), dir = c("both", "up", "down", "each"), p_value = 0.05, table_height = NULL, palette = NULL, coef = NULL )
plot_obj |
A ggplot object, typically the output of |
data2 |
Gene details: a data frame, or a DESeq2 / edgeR / limma
result object (see |
top_n |
Optional integer. When supplied, the |
sig_col |
Column used to rank significance when |
dir |
Direction to draw the |
p_value |
Significance threshold used for color-coding the p-value
column, and for filtering eligible genes when |
table_height |
Optional relative height of the table panel (the plot
panel is 3). By default ( |
palette |
Colors for the log2FC column. Default NULL takes the colors
of |
coef |
Coefficient to extract when |
A patchwork object that can be further composed or saved with
ggplot2::ggsave().
# Load example datasets data(all_genes) data(attention_genes) # Create a volcano plot and combine it with a gt gene table p <- ggvolc(all_genes, attention_genes, add_seg = TRUE) genes_table(p, attention_genes) # Auto-select the 10 most significant genes from the full table p2 <- ggvolc(all_genes, label_top = 10) genes_table(p2, all_genes, top_n = 10) # Top 8 of each direction (up to 16 rows) genes_table(p2, all_genes, top_n = 8, dir = "each")# Load example datasets data(all_genes) data(attention_genes) # Create a volcano plot and combine it with a gt gene table p <- ggvolc(all_genes, attention_genes, add_seg = TRUE) genes_table(p, attention_genes) # Auto-select the 10 most significant genes from the full table p2 <- ggvolc(all_genes, label_top = 10) genes_table(p2, all_genes, top_n = 10) # Top 8 of each direction (up to 16 rows) genes_table(p2, all_genes, top_n = 8, dir = "each")
This function creates a volcano plot using ggplot2 based on provided datasets. It is particularly useful for visualizing differential gene expression data.
ggvolc( data1, data2 = NULL, size_var = NULL, p_value = 0.05, fc = 1, sig_col = c("padj", "pvalue"), label_top = NULL, label_dir = c("both", "up", "down", "each"), title = NULL, interactive = FALSE, palette = "default", not_sig_color = NULL, down_reg_color = NULL, up_reg_color = NULL, add_seg = FALSE, show_counts = FALSE, highlight = NULL, highlight_colors = NULL, highlight_alpha = 0.5, flip = FALSE, facet_scales = NULL, coef = NULL )ggvolc( data1, data2 = NULL, size_var = NULL, p_value = 0.05, fc = 1, sig_col = c("padj", "pvalue"), label_top = NULL, label_dir = c("both", "up", "down", "each"), title = NULL, interactive = FALSE, palette = "default", not_sig_color = NULL, down_reg_color = NULL, up_reg_color = NULL, add_seg = FALSE, show_counts = FALSE, highlight = NULL, highlight_colors = NULL, highlight_alpha = 0.5, flip = FALSE, facet_scales = NULL, coef = NULL )
data1 |
The DE results to plot: a data frame, or a DESeq2
( |
data2 |
Genes to highlight and label: a data frame or DE object (same
auto-detection as |
size_var |
Variable for determining the size of points. Options are
|
p_value |
Threshold for statistical significance. Default is 0.05. |
fc |
Fold change threshold for determining upregulated or downregulated genes. Default is 1. |
sig_col |
Column used to call significance and to build the y-axis.
Either |
label_top |
Optional integer. When supplied, the |
label_dir |
Direction to draw the |
title |
Plot title. Default NULL (no title). |
interactive |
Logical. If TRUE, returns an interactive ggiraph
|
palette |
Colors for the plot: a preset name (see
|
not_sig_color, down_reg_color, up_reg_color
|
Colors for
non-significant, downregulated, and upregulated genes. When given, they
override the matching color from |
add_seg |
Logical. If TRUE, dashed lines will be added to the plot indicating the p-value and fold change thresholds. Default is FALSE. |
show_counts |
Logical. If TRUE, the number of significantly down- and upregulated genes is printed in the top corners of the plot (of each panel when comparing contrasts). Default FALSE. |
highlight |
Optional named list of gene sets to color, e.g.
|
highlight_colors |
Optional colors for the |
highlight_alpha |
Transparency of the |
flip |
Logical. If TRUE, swap the axes: log2 fold change on the y-axis and significance on the x-axis. Handy when comparing contrasts side by side, because the fold-change axis then lines up across the panels. Default FALSE. |
facet_scales |
When comparing contrasts, which axes each panel may set
for itself: |
coef |
For a multi-coefficient limma fit, the coefficient to plot; for
a |
You can pass the result objects of DESeq2, edgeR, and limma directly
(see de_table), or a data frame. Column names from all three
pipelines are detected and mapped automatically.
A ggplot2 object displaying the volcano plot, or, when
interactive = TRUE, a ggiraph girafe widget.
# Load example datasets included in the package data(all_genes) data(attention_genes) # Create a basic volcano plot with default settings # Points are colored by significance (p < 0.05, |log2FC| > 1) ggvolc(all_genes) # Highlight specific genes of interest with labels # These genes are shown with black borders and gene names ggvolc(all_genes, attention_genes) # Add dashed lines to indicate significance thresholds ggvolc(all_genes, attention_genes, add_seg = TRUE) # Significance is called on the adjusted p-value (FDR) by default; # use the raw p-value instead with: ggvolc(all_genes, sig_col = "pvalue") # Automatically label the 10 most significant genes ggvolc(all_genes, label_top = 10) # Label the top 10 upregulated genes only ggvolc(all_genes, label_top = 10, label_dir = "up") # Label the top 8 of each direction (up to 16 labels) ggvolc(all_genes, label_top = 8, label_dir = "each") # Give the plot a title ggvolc(all_genes, title = "Treated vs. control") # Show how many genes go up and down ggvolc(all_genes, show_counts = TRUE) # Color gene sets, e.g. a pathway ggvolc(all_genes, highlight = list(Set_A = all_genes$genes[1:15], Set_B = all_genes$genes[100:130])) # ... each set with its own transparency ggvolc(all_genes, highlight = list(Set_A = all_genes$genes[1:15], Set_B = all_genes$genes[100:130]), highlight_alpha = c(Set_A = 1, Set_B = 0.5)) # Compare contrasts side by side: a real stress time course ggvolc(stress_timecourse, label_top = 5, show_counts = TRUE) # Share the significance axis too ggvolc(stress_timecourse, label_top = 5, facet_scales = "fixed") # Fold change on the y-axis, significance on the x-axis ggvolc(stress_timecourse, label_top = 5, flip = TRUE) # Colorblind-safe colors, or any preset from ggvolc_palettes() ggvolc(all_genes, label_top = 10, palette = "okabe_ito") # Customize colors for up- and down-regulated genes ggvolc(all_genes, attention_genes, up_reg_color = "#E63946", down_reg_color = "#457B9D") # Scale point size by p-value instead of default ggvolc(all_genes, attention_genes, size_var = "pvalue") # Adjust significance thresholds (p-value and fold change) ggvolc(all_genes, p_value = 0.01, fc = 2) # edgeR-style input works directly edger_df <- data.frame( genes = paste0("gene", 1:50), logFC = rnorm(50, 0, 2), logCPM = runif(50, 5, 15), PValue = 10^-runif(50, 0, 6), FDR = 10^-runif(50, 0, 5) ) ggvolc(edger_df) # limma-style input works too limma_df <- data.frame( genes = paste0("gene", 1:50), logFC = rnorm(50, 0, 2), AveExpr = runif(50, 5, 15), t = rnorm(50), P.Value = 10^-runif(50, 0, 6), adj.P.Val = 10^-runif(50, 0, 5) ) ggvolc(limma_df) ## Not run: # DE objects work directly, no conversion needed ggvolc(DESeq2::results(dds)) ggvolc(edgeR::glmQLFTest(qlf_fit, coef = 2)) ggvolc(limma::eBayes(limma_fit), coef = "treatment") # Interactive volcano (requires the ggiraph package): hover a point to # see the gene name and its statistics ggvolc(all_genes, attention_genes, interactive = TRUE) ## End(Not run)# Load example datasets included in the package data(all_genes) data(attention_genes) # Create a basic volcano plot with default settings # Points are colored by significance (p < 0.05, |log2FC| > 1) ggvolc(all_genes) # Highlight specific genes of interest with labels # These genes are shown with black borders and gene names ggvolc(all_genes, attention_genes) # Add dashed lines to indicate significance thresholds ggvolc(all_genes, attention_genes, add_seg = TRUE) # Significance is called on the adjusted p-value (FDR) by default; # use the raw p-value instead with: ggvolc(all_genes, sig_col = "pvalue") # Automatically label the 10 most significant genes ggvolc(all_genes, label_top = 10) # Label the top 10 upregulated genes only ggvolc(all_genes, label_top = 10, label_dir = "up") # Label the top 8 of each direction (up to 16 labels) ggvolc(all_genes, label_top = 8, label_dir = "each") # Give the plot a title ggvolc(all_genes, title = "Treated vs. control") # Show how many genes go up and down ggvolc(all_genes, show_counts = TRUE) # Color gene sets, e.g. a pathway ggvolc(all_genes, highlight = list(Set_A = all_genes$genes[1:15], Set_B = all_genes$genes[100:130])) # ... each set with its own transparency ggvolc(all_genes, highlight = list(Set_A = all_genes$genes[1:15], Set_B = all_genes$genes[100:130]), highlight_alpha = c(Set_A = 1, Set_B = 0.5)) # Compare contrasts side by side: a real stress time course ggvolc(stress_timecourse, label_top = 5, show_counts = TRUE) # Share the significance axis too ggvolc(stress_timecourse, label_top = 5, facet_scales = "fixed") # Fold change on the y-axis, significance on the x-axis ggvolc(stress_timecourse, label_top = 5, flip = TRUE) # Colorblind-safe colors, or any preset from ggvolc_palettes() ggvolc(all_genes, label_top = 10, palette = "okabe_ito") # Customize colors for up- and down-regulated genes ggvolc(all_genes, attention_genes, up_reg_color = "#E63946", down_reg_color = "#457B9D") # Scale point size by p-value instead of default ggvolc(all_genes, attention_genes, size_var = "pvalue") # Adjust significance thresholds (p-value and fold change) ggvolc(all_genes, p_value = 0.01, fc = 2) # edgeR-style input works directly edger_df <- data.frame( genes = paste0("gene", 1:50), logFC = rnorm(50, 0, 2), logCPM = runif(50, 5, 15), PValue = 10^-runif(50, 0, 6), FDR = 10^-runif(50, 0, 5) ) ggvolc(edger_df) # limma-style input works too limma_df <- data.frame( genes = paste0("gene", 1:50), logFC = rnorm(50, 0, 2), AveExpr = runif(50, 5, 15), t = rnorm(50), P.Value = 10^-runif(50, 0, 6), adj.P.Val = 10^-runif(50, 0, 5) ) ggvolc(limma_df) ## Not run: # DE objects work directly, no conversion needed ggvolc(DESeq2::results(dds)) ggvolc(edgeR::glmQLFTest(qlf_fit, coef = 2)) ggvolc(limma::eBayes(limma_fit), coef = "treatment") # Interactive volcano (requires the ggiraph package): hover a point to # see the gene name and its statistics ggvolc(all_genes, attention_genes, interactive = TRUE) ## End(Not run)
Lists the color presets available through the palette argument of
ggvolc and genes_table. Each preset sets the
color of downregulated, non-significant, and upregulated genes.
ggvolc_palettes()ggvolc_palettes()
Presets marked colorblind_safe keep the up and down colors clearly
apart under simulated deuteranopia, protanopia, and tritanopia (checked
with colorspace). Several presets come from the
ltc palettes; ltc does not need to be
installed to use them.
You are not limited to these presets: palette also accepts a named
color vector such as c(down = "navy", up = "firebrick"). That makes
any palette usable, for example one from ltc:
pal <- ltc::ltc("maya"); ggvolc(all_genes, palette = c(down = pal[1], up = pal[4])).
A data frame with one row per preset and columns palette,
down, not_sig, up, colorblind_safe, and
source.
ggvolc_palettes() ggvolc(all_genes, palette = "okabe_ito") ggvolc(all_genes, palette = c(down = "navy", up = "firebrick"))ggvolc_palettes() ggvolc(all_genes, palette = "okabe_ito") ggvolc(all_genes, palette = c(down = "navy", up = "firebrick"))
Real DESeq2 results from an RNA-seq time course of wild-type fission yeast
(Schizosaccharomyces pombe) exposed to osmotic stress (1 M sorbitol).
Each element of the list compares one time point after stress with time 0,
so the list can be passed straight to ggvolc to compare the
contrasts side by side. The response is strongest at 30 minutes and fades
by 180 minutes.
stress_timecoursestress_timecourse
A named list of three data frames, "30 min vs 0 min",
"60 min vs 0 min", and "180 min vs 0 min", each with 6535
rows and the columns:
Character. Gene symbol, or the systematic ID when no symbol exists.
Numeric. Mean of normalized counts across all samples.
Numeric. log2 fold change versus time 0.
Numeric. Wald test p-value.
Numeric. Benjamini-Hochberg adjusted p-value.
The counts come from the Bioconductor data package fission
(wild-type samples only, 3 replicates per time point; genes with fewer than
10 reads in total removed). Results were computed with
DESeq2::DESeq() using design = ~ minute; see
data-raw/stress_timecourse.R in the package sources. As in any
DESeq2 output, padj is NA for genes removed by independent
filtering.
Leong HS, Dawson K, Wirth C, et al. (2014). A global non-coding RNA system modulates fission yeast protein levels in response to stress. Nature Communications 5:3947. doi:10.1038/ncomms4947. GEO accession GSE56761. Data via the Bioconductor package fission.
names(stress_timecourse) ggvolc(stress_timecourse, label_top = 5, show_counts = TRUE)names(stress_timecourse) ggvolc(stress_timecourse, label_top = 5, show_counts = TRUE)