Comments (10)
You need to learn how to make minimal reproducible examples. Here, I'll give you a starting point, but you'll have to take it from here. I'm not going to read your package code or install your package or look at an example that is more than maybe 30-40 lines of code total.
library(tidyverse)
data <- tibble(
x = 1:3,
y = 3:1,
a = factor(c("A", "A", "B"), levels = c("A", "B", "C"))
)
# green dot is missing from legend
ggplot(data, aes(x, y, color = a)) +
geom_point() +
scale_color_manual(
values = c(A = "red", B = "blue", C = "green")
)
# green dot is present
ggplot(data, aes(x, y, color = a)) +
geom_point(show.legend = TRUE) +
scale_color_manual(
values = c(A = "red", B = "blue", C = "green"),
drop = FALSE
)
Created on 2024-03-27 with reprex v2.0.2
from ggplot2.
Would it be a problem to just set show.legend = TRUE
in the functions that generate p1
and p2
?
Alternatively, you could possibly code something like the following. You may have to iterate over all layers and make sure you're actually modifying geom_point()
layers only.
library(tidyverse)
data <- tibble(
x = 1:3,
y = 3:1,
a = factor(c("A", "A", "B"), levels = c("A", "B", "C"))
)
# green dot is missing from legend
p <- ggplot(data, aes(x, y, color = a)) +
geom_point() +
scale_color_manual(
values = c(A = "red", B = "blue", C = "green"),
drop = FALSE
)
p
# turn on green dot after the fact
p$layers[[1]]$show.legend <- TRUE
p
Created on 2024-03-27 with reprex v2.0.2
from ggplot2.
Could you please create a minimal reproducible example of the exact behavior that is causing you problems? Just draw up a simple plot with one or more legends that don't look the way you'd think they should.
from ggplot2.
This all sounds very similar to #5728. TL;DR: Dropping key glyphs is intended, to include a layer's key glyph in the legend without the data being present, use show.legend = TRUE
.
from ggplot2.
@teunbrand @clauswilke
Thanks both for quick replies!!
Indeed it does sound like that previous issue. However, in my case the base plot is being returned from another package as ggplot2 object. So can't pass the show.legend = TRUE
in original geom_point
call. What is the best (or least hacky maybe) was to pass this parameter when modifying that original plot?
Best,
Sam
from ggplot2.
Again, please provide a minimal example that accurately represents your situation (maybe with a function that takes the plot object as input) so we can look into it and explore approaches.
from ggplot2.
Hi @clauswilke,
Working on re-creating essential aspects of functions without such heavy package dependencies. Working on recreating all the modifications that the original package does to the plot correctly and then how my function modifies that returned plot. Might be tomorrow before I can complete that but working on it.
I realize this isn't exactly minimal example because it's dependency heavy but in case it's help the full issue below does show the issue (requires Seurat; heavy dep).
Uses these two Seurat functions:
DimPlot
SingleDimPlot
Then modified by function in my package scCustomize:
DimPlot_scCustom
This section in particular is modifying the color levels of the plot generated by Seurat:
https://github.com/samuel-marsh/scCustomize/blob/fc7a282af3bef6e1cb816fac3b9229f536159238/R/Seurat_Plotting.R#L1892-L1935
# ggplot 3.5.0
install.packages("Seurat")
install.packages("scCustomize")
# plot with all levels present in both plots
DimPlot_scCustom(seurat_object = pbmc, split.by = "treatment")
# create subset without one level
data <- FetchData(object = pbmc, vars = c("treatment", "seurat_annotations"))
cells_remove <- data %>%
filter(treatment == "Treatment1" & seurat_annotations == "Naive CD4 T") %>%
rownames()
pbmc_subbed <- subset(pbmc, cells = cells_remove, invert = TRUE)
DimPlot_scCustom(seurat_object = pbmc_subbed, split.by = "treatment")
Running same thing with ggplot2 3.4.4 results in:
Again I realize this is the heavy version for sure and working on more minimal example that maintains plots correctly.
Thanks so much again for the quick replies!!
Best,
Sam
from ggplot2.
I'd also like to note that using facetting instead of plot composition might circumvent the issue altoghether. From my reading of the problem, both plots share the same layers, coordinates and colour scales so that should lend itself to facetting.
Another solution might be to 'cut the middleman' and construct plots de novo instead of wrapping plotting functions that wrap ggplot2. I'd find it very strange if Seurat doesn't provide accessors to wrangle the relevant data out of their data structures.
from ggplot2.
Hi @clauswilke,
Yes, I know how to make reproducible example, but as I mentioned was trying to ensure that example mirrored what was happening in original function in terms of how plot is output and was providing the heavy version in case it was helpful while I was working on reprex. I will need to check this vs. original function, ut the simplest version would be this:
library(ggplot2)
library(patchwork)
# Dummy data
data_plot <- data.frame(
UMAP1 = c(-4.232792, -4.892886, -5.508639, 11.332233, -7.450703),
UMAP2 = c(-4.152139, 10.985685, -7.211088, 3.161727, 1.092022),
group = factor(c("Group1", "Group2", "Group1", "Group1", "Group2")),
treatment = factor(c("treat1", "treat1", "treat1", "treat1", "treat2"))
)
rownames(data_plot) <- paste0("A", seq_len(5))
# colors to use
colors <- c("blue", "red")
names(colors) <- unique(data_plot$group)
# plot without subsetting data by treatment
ggplot(data_plot, aes(x = UMAP1, y = UMAP2, color = group)) +
geom_point() +
scale_color_manual(values = colors, drop = FALSE)
# get rownames of subsets
treat1_cells <- paste0("A", seq_len(4))
treat2_cells <- "A5"
# subset the data
data_plot_treat1 <- data_plot[treat1_cells, ]
data_plot_treat2 <- data_plot[treat2_cells, ]
# plot the subsets
p1 <- ggplot(data_plot_treat1, aes(x = UMAP1, y = UMAP2, color = group)) +
geom_point()
p2 <- ggplot(data_plot_treat2, aes(x = UMAP1, y = UMAP2, color = group)) +
geom_point()
# HERE is where my package comes in
# p1 nd p2 are returned from Seurat
# Then modified and wrapped by my package
p1_mod <- p1 + scale_color_manual(values = colors, drop = FALSE)
p2_mod <- p2 + scale_color_manual(values = colors, drop = FALSE)
plots <- wrap_plots(p1_mod, p2_mod) + plot_layout(guides = "collect")
plots
Created on 2024-03-27 with reprex v2.1.0
@teunbrand Seurat does have accessors to pull the required data out and make plot de novo. However, as goal of this particular is to extend the functionality of a Seurat function it was easier to use the output of that function. That way if there are changes in Seurat that effect function (structure of Seurat object changes, new parameters, bug fixes, etc) they are already present without having to keep as close an eye on the codebase if I was plotting de novo. Using patchwork for assembly worked best at time but I can see if faceting them could work here.
Best,
Sam
from ggplot2.
Hi @clauswilke,
Yes, I think I will put PR in to Seurat to add that to the base code for the function in question.
Thanks for the example with modifying the layers in output. I'll play around with that and faceting in the short-term until PR can be approved.
Thank you both @clauswilke and @teunbrand again for your help with this, I really appreciate it!!
Best,
Sam
from ggplot2.
Related Issues (20)
- Release ggplot2 3.5.1
- custom guide with `theme_void()` will throw a warning message HOT 1
- VSCode and ggplot (randomly) throw error "Error in UseMethod("depth")". HOT 7
- Feature request: flexible parametrisation of rectangles
- AsIs sometimes not preserved when computing geom parameters HOT 4
- Cryptic error when mis-specifying linetype HOT 6
- Version 3.5.0 or 3.5.1 cannot render a plot made with 3.4.4 HOT 2
- Standardising calls to `gpar()`
- Fill and color guides for factor with `drop=FALSE` don't show color. HOT 7
- `guide_coloursteps(show.limits = T)` produces strange lower limit HOT 1
- Warnings due to partial matching HOT 2
- Reproducible example for `position_jitter()` not working HOT 1
- geom_sf_label() returns an error HOT 3
- date_breaks and date_breaks minor don't check argument type HOT 2
- `scale_*_*` `labels` argument often doesn't work as expected with a function HOT 8
- geom_histogram produces wrong number of bins in special cases HOT 2
- x/ylim Arguments in coord_fixed Donβt Seem to Be Applied to Contours: HOT 1
- Feature request: allow adding aesthetics together HOT 2
- Adding bootstrap customization for stat_summary(fun.data="mean_cl_boot") HOT 1
- Have header font be part of theme specification HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ggplot2.