Plotting¶
All plot functions return plotnine.ggplot objects, which can be composed with + before rendering. Call .draw() to display or .save("output.pdf") to write to disk.
The make_network function is an exception: it returns a networkx.Graph.
from pyloseq import (
plot_bar, plot_richness, plot_ordination,
plot_heatmap, plot_tree, make_network, plot_network,
)
plot_bar¶
Stacked bar chart of OTU abundances. Internally calls psmelt to convert to long format before plotting.
Stack order is deterministic: sorted first by the x column, then by the fill column, matching R phyloseq's rendering.
# Group by sample type on x-axis, fill by phylum
p = plot_bar(ps, x="SampleType", fill="Phylum")
# Facet by sample type
p = plot_bar(ps, fill="Genus", facet_grid="SampleType ~")
# Compose with a plotnine theme
from plotnine import theme_bw
p = plot_bar(ps, fill="Phylum") + theme_bw()
pyloseq.plot_bar ¶
plot_bar(
ps: Phyloseq,
x: str = "Sample",
y: str = "Abundance",
fill: str | None = None,
facet_grid: str | None = None,
title: str | None = None,
) -> Any
Stacked bar chart of OTU/feature abundances.
Bars are ordered by x and stacked deterministically by fill so
that fill segments line up consistently across samples (matching R
phyloseq's behaviour).
R reference: plot_bar(physeq, x, y, fill, facet_grid, title)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ps
|
Phyloseq
|
|
required |
x
|
str
|
Column in the melted data to use as x-axis (default |
'Sample'
|
y
|
str
|
Column for bar height (default |
'Abundance'
|
fill
|
str | None
|
Column for bar fill colour (e.g. |
None
|
facet_grid
|
str | None
|
Facet formula string (e.g. |
None
|
title
|
str | None
|
Plot title. |
None
|
Returns:
| Type | Description |
|---|---|
ggplot
|
|
plot_richness¶
Alpha diversity plot faceted by measure. By default each panel shows a box-and-whisker summary; set boxplot=False for a points-only view (useful when x groups only a few samples and boxes add noise):
p = plot_richness(ps, x="SampleType", color="SampleType",
measures=["Shannon", "Simpson"])
p.draw()
# Points only — no boxes
p = plot_richness(ps, x="SampleType", color="SampleType", boxplot=False)
Standard-error whiskers are drawn automatically for measures that have a corresponding se.* column in the estimate_richness output (currently only se.chao1).
Setting x="samples" (the default) puts individual sample names on the x-axis. Set x to any column in sample_data to group or aggregate:
# Individual samples, coloured by environment type
p = plot_richness(ps, x="samples", color="SampleType")
# Boxplots by environment type
p = plot_richness(ps, x="SampleType", color="SampleType")
pyloseq.plot_richness ¶
plot_richness(
ps: Phyloseq,
x: str = "samples",
color: str | None = None,
measures: list[str] | None = None,
title: str | None = None,
boxplot: bool = True,
) -> Any
Alpha diversity box-and-point plots, faceted by measure.
Standard-error whiskers are drawn for any measure that has a matching
se.<measure> column from :func:estimate_richness (e.g. se.chao1,
se.ACE), matching R phyloseq.
R reference: plot_richness(physeq, x, color, measures, title)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ps
|
Phyloseq
|
|
required |
x
|
str
|
Sample metadata column for x-axis. Use |
'samples'
|
color
|
str | None
|
Sample metadata column for point colour. |
None
|
measures
|
list[str] | None
|
Diversity measures to include; default is all. |
None
|
title
|
str | None
|
Plot title. |
None
|
boxplot
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
ggplot
|
|
plot_rarefaction_curve¶
Rarefaction curves showing observed richness as a function of sequencing depth. For each sample the OTU counts are subsampled (without replacement) at n_steps evenly-spaced depths between step and the minimum sample depth, and the number of distinct observed taxa is counted at each depth:
from pyloseq import plot_rarefaction_curve
p = plot_rarefaction_curve(ps, step=500, n_steps=30)
p.draw()
# Colour curves by a metadata variable
p = plot_rarefaction_curve(ps, step=200, n_steps=40, color="SampleType")
All curves share the same rightmost depth (the minimum sample depth across all samples), so the plot shows where each sample's curve plateaus relative to the overall sequencing effort.
The returned ggplot's data attribute contains columns Sample, Depth, and Observed (plus the color column if one was requested), enabling further customisation:
p = plot_rarefaction_curve(ps, step=500, n_steps=20, rng_seed=42)
p + theme_bw() + labs(title="Rarefaction curves")
Note
Each depth point uses an independent random draw, not a cumulative one. The curves show expected richness at each depth — use a fixed rng_seed for reproducible figures, and increase n_steps for smoother curves.
pyloseq.plot_rarefaction_curve ¶
plot_rarefaction_curve(
ps: Phyloseq,
step: int = 500,
n_steps: int = 30,
color: str | None = None,
rng_seed: int | None = None,
title: str | None = None,
) -> Any
Rarefaction curves showing observed richness vs. sequencing depth.
For each sample a curve is drawn by randomly subsampling (without
replacement) the reads at n_steps depths between step and the
minimum sample depth, then counting the number of distinct observed taxa
at each depth. The minimum depth sets the right-hand end of all curves
so that every sample reaches the same maximum depth point.
R reference: vegan::rarecurve(t(otu_table(physeq)), step=...) or microbiome::plot_richness_estimates (depth-based variant)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ps
|
Phyloseq
|
|
required |
step
|
int
|
Starting depth for the rarefaction grid (first subsampling depth). |
500
|
n_steps
|
int
|
Number of evenly-spaced depth points from |
30
|
color
|
str | None
|
Column in |
None
|
rng_seed
|
int | None
|
Seed for the subsampling RNG. Pass |
None
|
title
|
str | None
|
Plot title. |
None
|
Returns:
| Type | Description |
|---|---|
ggplot
|
The underlying |
plot_ordination¶
Scatter plot of ordination results. The kind parameter controls what is plotted:
kind |
What is plotted |
|---|---|
"samples" |
Sample coordinates (default) |
"taxa" |
Feature/taxa scores (requires ordination with feature scores, e.g. CA, RDA) |
"biplot" |
Samples and taxa together, taxa scores rescaled to sample axis range |
"split" |
Samples and taxa side-by-side in facets |
"scree" |
Proportion of variance explained per axis |
from pyloseq import ordinate, plot_ordination
ord_result = ordinate(ps, method="PCoA", distance="bray")
# Basic sample scatter
p = plot_ordination(ps, ord_result, color="SampleType")
p.draw()
# With convex hulls per colour group
p = plot_ordination(ps, ord_result, color="SampleType", show_hull=True)
# Scree plot
p = plot_ordination(ps, ord_result, kind="scree")
# Return the DataFrame instead of a plot (for custom plotting)
df = plot_ordination(ps, ord_result, just_df=True)
Note
kind="taxa" and kind="biplot" require an ordination that produces feature scores, such as CA, CCA, or RDA. PCoA and NMDS do not produce feature scores; using those with kind="taxa" raises pyloseqValidationError.
pyloseq.plot_ordination ¶
plot_ordination(
ps: Phyloseq,
ord: Any,
kind: str = "samples",
color: str | None = None,
shape: str | None = None,
label: str | None = None,
title: str | None = None,
show_hull: bool = False,
just_df: bool = False,
**kwargs: Any,
) -> Any
Scatter plot of ordination results.
R reference: plot_ordination(physeq, ordination, type, color, shape, label, title, justDF)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ps
|
Phyloseq
|
|
required |
ord
|
Any
|
|
required |
kind
|
str
|
One of |
'samples'
|
color
|
str | None
|
Sample/taxa metadata column for point colour. |
None
|
shape
|
str | None
|
Sample metadata column for point shape. |
None
|
label
|
str | None
|
Column to annotate points with text labels. |
None
|
title
|
str | None
|
Plot title. |
None
|
show_hull
|
bool
|
If |
False
|
just_df
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
ggplot or DataFrame
|
|
plot_heatmap¶
Heatmap of OTU abundances across samples. By default, rows and columns are reordered by an ordination to group similar taxa and samples together:
Pass method=None to skip ordination entirely and preserve the original sample and taxa order from the Phyloseq object:
The trans parameter applies a transformation before plotting. Zero values become NaN and render using na_value rather than the low-end gradient colour:
trans |
Transformation |
|---|---|
None |
Raw values |
"log4" |
log₄(x), zeros → na_value |
Use label to replace x-axis sample-name tick labels with a sample_data variable, and taxa_label to replace y-axis taxa-name tick labels with a taxonomic rank. Ordering (from ordination or original order) is unaffected — only the tick text changes. These mirror R phyloseq's sample.label and taxa.label:
# Label x-axis ticks by treatment group, y-axis ticks by phylum
p = plot_heatmap(ps, method="PCoA", label="TreatmentGroup", taxa_label="Phylum")
pyloseq.plot_heatmap ¶
plot_heatmap(
ps: Phyloseq,
method: str | None = "NMDS",
distance: str = "bray",
trans: str | None = "log4",
low: str = "#000033",
high: str = "#66CCFF",
na_value: str = "black",
title: str | None = None,
label: str | None = None,
taxa_label: str | None = None,
) -> Any
Abundance heatmap with samples and taxa reordered by ordination.
Both axes are reordered using the ordination result (samples along x,
taxa/OTUs along y), matching R phyloseq. Zero/NA abundances are mapped
to na_value rather than the gradient's low colour.
R reference: plot_heatmap(physeq, method, distance, trans, low, high, na.value, title, sample.label, taxa.label)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ps
|
Phyloseq
|
|
required |
method
|
str | None
|
Ordination method used to reorder samples and taxa. Pass |
'NMDS'
|
distance
|
str
|
Distance metric for ordination. |
'bray'
|
trans
|
str | None
|
Transformation applied to abundances before plotting.
|
'log4'
|
low
|
str
|
Gradient colour endpoints. |
'#000033'
|
high
|
str
|
Gradient colour endpoints. |
'#000033'
|
na_value
|
str
|
Colour for zero/NA cells. |
'black'
|
title
|
str | None
|
Plot title. |
None
|
label
|
str | None
|
Column in |
None
|
taxa_label
|
str | None
|
Taxonomic rank (e.g. |
None
|
Returns:
| Type | Description |
|---|---|
ggplot
|
|
plot_tree¶
Phylogenetic tree visualization. Requires phy_tree:
method parameter:
"treeonly"— draw the tree structure only"sampledodge"— dodge sample points along the tips by metadata
# Tree with phylum labels at tips
p = plot_tree(ps, method="treeonly", label_tips="Phylum", ladderize=True)
# Sample-dodge mode: show samples by environment type at tips
p = plot_tree(ps, method="sampledodge", color="SampleType", size="Abundance")
pyloseq.plot_tree ¶
plot_tree(
ps: Phyloseq,
method: str = "sampledodge",
color: str | None = None,
shape: str | None = None,
size: str | None = None,
label_tips: str | None = None,
text_size: float | None = None,
sizebase: float = 5.0,
base_spacing: float = 0.02,
min_abundance: float = float("inf"),
ladderize: bool | str = False,
justify: str = "jagged",
plot_margin: float = 0.2,
figure_size: tuple[float, float] | None = None,
title: str | None = None,
) -> Any
Phylogenetic tree with per-sample points at the tips.
R reference: plot_tree(physeq, method, color, shape, size, label.tips, text.size, sizebase, base.spacing, min.abundance, ladderize, justify, plot.margin, title)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ps
|
Phyloseq
|
|
required |
method
|
str
|
|
'sampledodge'
|
color
|
str | None
|
Sample metadata or |
None
|
shape
|
str | None
|
Sample metadata column for point shape. |
None
|
size
|
str | None
|
|
None
|
label_tips
|
str | None
|
|
None
|
text_size
|
float | None
|
Font size for tip labels. Auto-scaled from tip count when |
None
|
sizebase
|
float
|
Log base for the abundance → size transform. |
5.0
|
base_spacing
|
float
|
Fractional x-step between dodged sample points, as a proportion of the maximum tip x value. |
0.02
|
min_abundance
|
float
|
Abundance threshold for printing per-point text labels. Default
|
float('inf')
|
ladderize
|
bool | str
|
|
False
|
justify
|
str
|
|
'jagged'
|
plot_margin
|
float
|
Fractional right-margin added beyond the last dodged point so that tip labels are not clipped. |
0.2
|
figure_size
|
tuple[float, float] | None
|
|
None
|
title
|
str | None
|
Plot title. |
None
|
Returns:
| Type | Description |
|---|---|
ggplot
|
|
make_network / plot_network¶
make_network builds a networkx.Graph where nodes are samples and edges connect samples whose distance is below max_dist:
from pyloseq import make_network, plot_network
g = make_network(ps, max_dist=0.4, distance="bray")
p = plot_network(g, ps, color="SampleType", label="SampleID")
p.draw()
The distance parameter accepts either a metric name string (see distance) or a precomputed skbio.stats.distance.DistanceMatrix — mirroring R's plot_net(distance=as.dist(...)) pattern. This makes it straightforward to use phylogenetic distances from gunifrac:
from pyloseq import gunifrac, make_network, plot_network
results = gunifrac(ps)
g = make_network(ps, distance=results["d_0.5"], max_dist=0.5)
p = plot_network(g, ps, color="SampleType")
p.draw()
Edge width is scaled inversely by distance: edges between more-similar samples appear thicker, matching R's plot_net. If the shape aesthetic maps to more than 6 unique values, the shape legend is suppressed automatically (shapes are still distinct in the plot) and a warning is issued — plotnine's default shape palette has only 6 entries.
Node attributes from sample_data are attached to each node automatically, making the graph available for further networkx analysis.
pyloseq.make_network ¶
make_network(
ps: Phyloseq,
kind: str = "samples",
distance: str | Any = "jaccard",
max_dist: float = 0.4,
keep_isolates: bool = False,
**kwargs: Any,
) -> Any
Build a sample (or taxa) network based on a distance threshold.
Edges are drawn between nodes whose distance is strictly less than
max_dist (matching R phyloseq's max.dist semantics).
R reference: make_network(physeq, type, distance, max.dist, keep.isolates) R reference: plot_net(physeq, distance=as.dist(...), ...) — precomputed DM
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ps
|
Phyloseq
|
|
required |
kind
|
str
|
|
'samples'
|
distance
|
str | Any
|
Distance metric string (see :func: |
'jaccard'
|
max_dist
|
float
|
Maximum distance for an edge to be drawn (strict |
0.4
|
keep_isolates
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
Graph
|
|
pyloseq.plot_network ¶
plot_network(
g: Any,
ps: Phyloseq,
color: str | None = None,
shape: str | None = None,
line_weight: float = 0.5,
line_color: str = "grey",
line_alpha: float = 0.4,
point_size: float = 5.0,
label: str | None = None,
layout: str = "fruchterman_reingold",
title: str | None = None,
) -> Any
Plot a network graph as a ggplot scatter.
R reference: plot_network(ig, physeq, color, shape, line_weight, line_color, line_alpha, point_size, label, layout, title)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
g
|
Any
|
|
required |
ps
|
Phyloseq
|
|
required |
color
|
str | None
|
Node attribute column for colour. |
None
|
shape
|
str | None
|
Node attribute column for point shape. |
None
|
line_weight
|
float
|
Edge line width. |
0.5
|
line_color
|
str
|
Edge colour. |
'grey'
|
line_alpha
|
float
|
Edge opacity. |
0.4
|
point_size
|
float
|
Node point size. |
5.0
|
label
|
str | None
|
Node attribute column (or |
None
|
layout
|
str
|
NetworkX layout algorithm name (e.g. |
'fruchterman_reingold'
|
title
|
str | None
|
Plot title. |
None
|
Returns:
| Type | Description |
|---|---|
ggplot
|
|