Skip to content

Fix behavior of fill.by / y.max / same.y.lims parameters in RidgePlot#10424

Open
anashen wants to merge 8 commits into
mainfrom
fix/ridgeplot-param-behavior
Open

Fix behavior of fill.by / y.max / same.y.lims parameters in RidgePlot#10424
anashen wants to merge 8 commits into
mainfrom
fix/ridgeplot-param-behavior

Conversation

@anashen

@anashen anashen commented Jul 13, 2026

Copy link
Copy Markdown
Member

Summary

Closes #10421 by @samuel-marsh.

This PR proposes the following:

  • Change the default value of the fill.by parameter.
    • The default value in the documentation was "feature", but due to overrides by ExIPlot, the default was actually "ident". Changing this to NULL, and picking a different default inside the function (ident if stack if FALSE, feature otherwise) helps to clarify this behavior.
  • Compute y axis limits properly if same.y.lims = TRUE. Add noise as necessary, following logic in MultiExIPlot, then apply this to all plots.
  • Add parameter fill.by to SingleExIPlot. The default is "ident" so complete backwards compatibility is maintained (across calls to this function, for example in other visualization functions).
  • Apply the proper limits to the axis as requested.

Reprex

suppressPackageStartupMessages({
  library(SeuratData)
  library(dplyr)
  library(patchwork)
})
#> Warning: package 'dplyr' was built under R version 4.5.2

# must be on this branch
devtools::load_all("~/seurat", quiet = TRUE)
#> Warning: package 'sp' was built under R version 4.5.2

pbmc <- suppressWarnings(suppressMessages(UpdateSeuratObject(pbmc3k.final))) %>% subset(seurat_annotations %in% c("Platelet", "DC", "CD8 T", "CD14+ Mono"))

# fill.by
# note that fill.by = "feature" is not informative unless stack = TRUE
RidgePlot(pbmc, features = "CD3E", fill.by = "ident") /
  RidgePlot(pbmc, features = "CD3E", fill.by = "feature")
#> Picking joint bandwidth of 0.0808
#> Picking joint bandwidth of 0.0808

# same.y.lims
RidgePlot(pbmc, features = c("CD3E", "LYZ"), same.y.lims = FALSE) /
  RidgePlot(pbmc, features = c("CD3E", "LYZ"), same.y.lims = TRUE)
#> Scale for x is already present.
#> Adding another scale for x, which will replace the existing scale.
#> Scale for x is already present.
#> Adding another scale for x, which will replace the existing scale.
#> Picking joint bandwidth of 0.0808
#> 
#> Picking joint bandwidth of 0.376
#> 
#> Picking joint bandwidth of 0.0808
#> 
#> Picking joint bandwidth of 0.376
#> Warning: Removed 1 row containing non-finite outside the scale range
#> (`stat_density_ridges()`).

# y.max
RidgePlot(pbmc, features = "CCL5") /
  RidgePlot(pbmc, features = "CCL5", y.max = 3)
#> Picking joint bandwidth of 0.176
#> Picking joint bandwidth of 0.201
#> Warning: Removed 250 rows containing non-finite outside the scale range
#> (`stat_density_ridges()`).

# stacked fill.by
RidgePlot(pbmc, features = c("CCL5", "LYZ", "CD3E"), stack = TRUE, fill.by = "ident") /
  RidgePlot(pbmc, features = c("CCL5", "LYZ", "CD3E"), stack = TRUE, fill.by = "feature")
#> Picking joint bandwidth of 0.176
#> Picking joint bandwidth of 0.376
#> Picking joint bandwidth of 0.0808
#> Picking joint bandwidth of 0.176
#> Picking joint bandwidth of 0.376
#> Picking joint bandwidth of 0.0808

# stacked same.y.lims
RidgePlot(pbmc, features = c("CCL5", "LYZ", "CD3E"), stack = TRUE, same.y.lims = TRUE)
#> Picking joint bandwidth of 0.176
#> Picking joint bandwidth of 0.376
#> Picking joint bandwidth of 0.0808

Created on 2026-07-13 with reprex v2.1.1

Copilot AI review requested due to automatic review settings July 13, 2026 19:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses reported bugs in Seurat’s RidgePlot() parameter behavior by clarifying fill.by defaults, ensuring fill.by is propagated into the underlying plot builder, and improving shared axis-limit handling for ridge plots.

Changes:

  • Updates RidgePlot(fill.by=) to default to NULL and resolve the effective default based on stack.
  • Adds fill.by support to SingleExIPlot() and threads it through ExIPlot().
  • Attempts to compute and apply shared x-axis limits for ridge plots when same.y.lims = TRUE (and incorporate y.max).

Reviewed changes

Copilot reviewed 1 out of 3 changed files in this pull request and generated 5 comments.

File Description
R/visualization.R Implements fill.by defaulting, propagates fill.by into SingleExIPlot, and adds ridge shared-limits computation/application logic.
man/SingleExIPlot.Rd Documents new fill.by parameter for SingleExIPlot().
man/RidgePlot.Rd Updates RidgePlot() signature to reflect fill.by = NULL default.
Files not reviewed (2)
  • man/RidgePlot.Rd: Generated file
  • man/SingleExIPlot.Rd: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread R/visualization.R
Comment thread R/visualization.R
Comment thread R/visualization.R
Comment on lines 9064 to 9066
if (!is.data.frame(x = data) || ncol(x = data) != 1) {
stop("'SingleExIPlot requires a data frame with 1 column")
}
Comment thread R/visualization.R
Comment on lines 9159 to 9163
jitter <- geom_jitter(width = 0, size = pt.size, alpha = alpha, show.legend = FALSE)
log.scale <- scale_x_log10()
axis.scale <- function(...) {
invisible(x = NULL)
log.scale <- scale_x_log10(expand = c(0, 0))
axis.scale <- function(x.min, x.max) {
scale_x_continuous(expand = c(0, 0), limits = c(x.min, x.max))
}
Comment thread R/visualization.R
Comment on lines +564 to 565
fill.by <- fill.by %||% if (stack) 'feature' else 'ident'
return(ExIPlot(
@anashen
anashen force-pushed the fix/ridgeplot-param-behavior branch from 5c2c7f9 to a3a4abd Compare July 13, 2026 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: Multiple RidgePlot parameters appear to be broken

2 participants