Skip to content

Commit 07780d3

Browse files
committed
feat(ClonalResidency): allow mulitple specific comparisons for groups
1 parent 83b07f5 commit 07780d3

File tree

2 files changed

+71
-36
lines changed

2 files changed

+71
-36
lines changed

R/clonalcompositionplot.R

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -407,12 +407,12 @@ ClonalLengthPlot <- function(
407407
#' @keywords internal
408408
DummyClonalScatterPlot <- function(df, title, group_by, scatter_cor, size_by, ...) {
409409
if (nrow(df) == 0) {
410-
stop("No data found for the group_by: ", group_by,
410+
stop("[ClonalResidencyPlot] No data found for the group_by: ", group_by,
411411
". Did you specify the correct 'group_by'/'groups' parameters?")
412412
}
413413
pair <- unique(as.character(df[[group_by]]))
414414
if (length(pair) != 2) {
415-
stop("The group_by should have exactly 2 unique values.")
415+
stop("[ClonalResidencyPlot] The group_by should have exactly 2 unique values.")
416416
}
417417

418418
exponent <- function(x) { floor(log10(abs(x))) }
@@ -594,7 +594,9 @@ DummyClonalScatterPlot <- function(df, title, group_by, scatter_cor, size_by, ..
594594
#' @param group_by The column name in the meta data to group the cells. Default: "Sample"
595595
#' @param groups The groups to compare. Default is NULL.
596596
#' If NULL, all the groups in `group_by` will be compared.
597-
#' Note that for "scatter" plot, only two groups can be compared.
597+
#' Note that for "scatter" plot, only two groups can be compared. So when there are more than two groups,
598+
#' the combination of the pairs will be used.
599+
#' For "scatter" plot, the groups can be specified as the comparisons separated by ":", e.g. "L:B", "Y:X".
598600
#' @param facet_by The column name in the meta data to facet the plots. Default: NULL
599601
#' @param split_by The column name in the meta data to split the plots. Default: NULL
600602
#' @param split_by_sep The separator used to concatenate the split_by when multiple columns are used.
@@ -616,7 +618,7 @@ DummyClonalScatterPlot <- function(df, title, group_by, scatter_cor, size_by, ..
616618
#' @return A ggplot object or a list if `combine` is FALSE
617619
#' @export
618620
#' @importFrom utils combn
619-
#' @importFrom dplyr distinct rename_with select across starts_with ends_with
621+
#' @importFrom dplyr distinct rename_with select across starts_with ends_with %>% filter
620622
#' @importFrom tidyr pivot_longer separate pivot_wider unite
621623
#' @importFrom scRepertoire clonalScatter
622624
#' @importFrom plotthis ScatterPlot VennDiagram UpsetPlot
@@ -628,17 +630,20 @@ DummyClonalScatterPlot <- function(df, title, group_by, scatter_cor, size_by, ..
628630
#' samples = c("P17B", "P17L", "P18B", "P18L", "P19B","P19L", "P20B", "P20L"))
629631
#' data <- scRepertoire::addVariable(data,
630632
#' variable.name = "Type",
631-
#' variables = rep(c("B", "L"), 4)
633+
#' variables = rep(c("B", "L", "X", "Y"), 2)
632634
#' )
633635
#' data <- scRepertoire::addVariable(data,
634636
#' variable.name = "Subject",
635637
#' variables = rep(c("P17", "P18", "P19", "P20"), each = 2)
636638
#' )
637639
#'
638640
#' ClonalResidencyPlot(data, groups = c("P18B", "P18L"))
639-
#' ClonalResidencyPlot(data, group_by = "Type", split_by = "Subject")
640-
#' ClonalResidencyPlot(data, plot_type = "venn", groups = c("B", "L"), group_by = "Type",
641+
#' ClonalResidencyPlot(data, group_by = "Type", groups = c("L", "B"),
642+
#' split_by = "Subject")
643+
#' ClonalResidencyPlot(data, group_by = "Type", groups = c("L:B", "Y:X"),
641644
#' split_by = "Subject")
645+
#' ClonalResidencyPlot(data, plot_type = "venn", groups = c("B", "L"),
646+
#' group_by = "Type", split_by = "Subject")
642647
#' ClonalResidencyPlot(data, plot_type = "upset", groups = c("P18B", "P18L"))
643648
#' }
644649
ClonalResidencyPlot <- function(
@@ -648,8 +653,8 @@ ClonalResidencyPlot <- function(
648653
order = list(), combine = TRUE, nrow = NULL, ncol = NULL, byrow = TRUE, ...
649654
) {
650655

651-
stopifnot("ClonalResidencyPlot supports only a single group_by column" = length(group_by) == 1)
652-
stopifnot("'facet_by' is not supported for 'ClonalResidencyPlot'" = is.null(facet_by))
656+
stopifnot("[ClonalResidencyPlot] only a single `group_by` column supported" = length(group_by) == 1)
657+
stopifnot("[ClonalResidencyPlot] 'facet_by' is not supported" = is.null(facet_by))
653658

654659
plot_type <- match.arg(plot_type)
655660
scatter_size_by <- match.arg(scatter_size_by)
@@ -664,44 +669,69 @@ ClonalResidencyPlot <- function(
664669
}
665670
}
666671

667-
groups <- groups %||% unique(data[[group_by]])
672+
# handle the groups
673+
# the order of groups should override the order in the data, even specified by `order`
674+
if (is.null(groups)) {
675+
if (!is.factor(data[[group_by]])) {
676+
data[[group_by]] <- factor(data[[group_by]])
677+
}
678+
groups <- levels(data[[group_by]])
679+
} else {
680+
groups <- unique(groups)
681+
if (any(grepl(":", groups, fixed = TRUE))) {
682+
if (!identical(plot_type, "scatter")) {
683+
stop("[ClonalResidencyPlot] The 'groups' parameter should not contain ':' for non-scatter plots.")
684+
}
685+
if (!all(grepl(":", groups, fixed = TRUE))) {
686+
stop("[ClonalResidencyPlot] All 'groups' should contain ':' for scatter plot if any of them does.")
687+
}
688+
lvls <- rev(unique(rev(unlist(strsplit(groups, ":", fixed = TRUE)))))
689+
if (any(!lvls %in% data[[group_by]])) {
690+
stop(paste0("[ClonalResidencyPlot] '", paste(setdiff(lvls, data[[group_by]]), collapse = ", "), "' in `groups` parameter are not present in the data."))
691+
}
692+
data[[group_by]] <- factor(data[[group_by]], levels = lvls)
693+
} else {
694+
data[[group_by]] <- factor(data[[group_by]], levels = groups)
695+
}
696+
}
697+
668698
if (plot_type == "scatter") {
669699
if (!is.null(split_by)) {
670700
data <- unite(data, ".split", split_by, sep = split_by_sep, remove = FALSE)
671701
} else {
672702
data$.split <- "..."
673703
}
674704
data <- split(data, data$.split)
675-
spdata <- list()
676-
if (!is.list(groups)) {
705+
if (any(grepl(":", groups, fixed = TRUE))) {
706+
groups <- lapply(groups, function(g) {
707+
gs <- strsplit(g, ":", fixed = TRUE)[[1]]
708+
if (length(gs) != 2) {
709+
stop("[ClonalResidencyPlot] The 'groups' parameter should contain exactly two values separated by ':' for scatter plot.")
710+
}
711+
gs <- trimws(gs)
712+
gs
713+
})
714+
} else {
677715
groups <- as.list(as.data.frame(combn(groups, 2, simplify = TRUE)))
678716
}
679-
for (spname in names(data)) {
680-
sdata <- data[[spname]]
681-
for (gp in groups) {
682-
gname <- paste(gp, collapse = " - ")
683-
gname <- ifelse(identical(spname, "..."), gname, paste(spname, gname, sep = ": "))
684-
spdata[[gname]] <- sdata[sdata[[group_by]] %in% gp, , drop = FALSE]
717+
718+
plots <- list()
719+
for (nm in names(data)) {
720+
for (g in groups) {
721+
d <- data[[nm]] %>% filter(!!sym(group_by) %in% g)
722+
if (length(unique(as.character(d[[group_by]]))) != 2) {
723+
warning(paste0("[ClonalResidencyPlot] Not both groups '", paste(g, collapse = ", "), "' is not present in the data for '", nm, "'. Skipping."))
724+
next
725+
}
726+
d[[group_by]] <- factor(d[[group_by]], levels = g)
727+
plots[[length(plots) + 1]] <- DummyClonalScatterPlot(d, nm, group_by, scatter_cor, scatter_size_by, ...)
685728
}
686729
}
687-
if (is.null(nrow) && is.null(ncol) && isTRUE(byrow) && length(groups) > 1 && length(data) > 1) {
688-
nrow <- length(data)
689-
}
690-
data <- spdata
691-
rm(spdata)
692-
} else {
693-
groups <- unique(unlist(groups))
694-
}
695-
696-
if (plot_type == "scatter") {
697-
plots <- lapply(names(data), function(nm) {
698-
DummyClonalScatterPlot(data[[nm]], nm, group_by, scatter_cor, scatter_size_by, ...)
699-
})
700730

701731
combine_plots(plots, combine = combine, nrow = nrow, ncol = ncol, byrow = byrow)
702732
} else if (plot_type == "venn") {
703733
if (length(groups) > 4) {
704-
stop("Too many groups for venn plot. Please use 'upset' plot instead.")
734+
stop("[ClonalResidencyPlot] Too many groups for venn plot. Please use 'upset' plot instead.")
705735
}
706736
data <- data[data[[group_by]] %in% groups, , drop = FALSE]
707737
data <- data[data$count > 0, , drop = FALSE]

man/ClonalResidencyPlot.Rd

Lines changed: 9 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)