diff --git a/NAMESPACE b/NAMESPACE index 7c9a52af..01ec53b3 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -155,6 +155,7 @@ importFrom(rlang,enquo) importFrom(rlang,enquos) importFrom(rlang,flatten_if) importFrom(rlang,inform) +importFrom(rlang,is_quosure) importFrom(rlang,is_spliced) importFrom(rlang,quo) importFrom(rlang,quo_is_missing) @@ -162,6 +163,7 @@ importFrom(rlang,quo_is_null) importFrom(rlang,quo_is_symbol) importFrom(rlang,quo_is_symbolic) importFrom(rlang,quo_name) +importFrom(rlang,quo_set_env) importFrom(rlang,quo_squash) importFrom(rlang,set_names) importFrom(scales,extended_breaks) diff --git a/R/methods.R b/R/methods.R index c79c3d9f..d9de0427 100755 --- a/R/methods.R +++ b/R/methods.R @@ -477,10 +477,10 @@ setGeneric("scale_abundance", function(.data, # Attach column internals add_tt_columns( - !!.sample, - !!.transcript, - !!.abundance, - !!(function(x, v) enquo(v))(x,!!value_scaled) + !!(.sample |> drop_enquo_env()), + !!(.transcript |> drop_enquo_env()), + !!(.abundance |> drop_enquo_env()), + !!(((function(x, v) enquo(v))(x,!!value_scaled)) |> drop_enquo_env()) ) @@ -698,10 +698,10 @@ setGeneric("quantile_normalise_abundance", function(.data, # Attach column internals add_tt_columns( - !!.sample, - !!.transcript, - !!.abundance, - !!(function(x, v) enquo(v))(x,!!value_scaled) + !!(.sample |> drop_enquo_env()), + !!(.transcript |> drop_enquo_env()), + !!(.abundance |> drop_enquo_env()), + !!(((function(x, v) enquo(v))(x,!!value_scaled)) |> drop_enquo_env()) ) @@ -3132,6 +3132,7 @@ setGeneric("identify_abundant", function(.data, .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7) standardGeneric("identify_abundant")) @@ -3142,6 +3143,7 @@ setGeneric("identify_abundant", function(.data, .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7) { @@ -3250,6 +3252,7 @@ setGeneric("identify_abundant", function(.data, edgeR::filterByExpr( min.count = minimum_counts, group = string_factor_of_interest, + design = design, min.prop = minimum_proportion ) %>% not() |> @@ -3345,6 +3348,7 @@ setGeneric("keep_abundant", function(.data, .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7) standardGeneric("keep_abundant")) @@ -3355,6 +3359,7 @@ setGeneric("keep_abundant", function(.data, .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7) { @@ -3387,6 +3392,7 @@ setGeneric("keep_abundant", function(.data, .transcript = !!.transcript, .abundance = !!.abundance, factor_of_interest = !!factor_of_interest, + design = design, minimum_counts = minimum_counts, minimum_proportion = minimum_proportion ) |> diff --git a/R/methods_SE.R b/R/methods_SE.R index f3e8d1f5..ec70b7be 100755 --- a/R/methods_SE.R +++ b/R/methods_SE.R @@ -196,7 +196,7 @@ setMethod("tidybulk", "RangedSummarizedExperiment", .tidybulk_se) memorise_methods_used(c("edger", "tmm")) %>% # Attach column internals - add_tt_columns(.abundance_scaled = !!(function(x, v) enquo(v))(x,!!as.symbol(value_scaled))) + add_tt_columns(.abundance_scaled = !!(((function(x, v) enquo(v))(x,!!as.symbol(value_scaled))) |> drop_enquo_env()) ) } @@ -321,7 +321,7 @@ setMethod("scale_abundance", memorise_methods_used(c("quantile")) %>% # Attach column internals - add_tt_columns(.abundance_scaled = !!(function(x, v) enquo(v))(x,!!as.symbol(value_scaled))) + add_tt_columns(.abundance_scaled = !!(((function(x, v) enquo(v))(x,!!as.symbol(value_scaled))) |> drop_enquo_env()) ) } @@ -953,8 +953,7 @@ setMethod("remove_redundancy", memorise_methods_used("sva") %>% # Attach column internals - add_tt_columns(.abundance_adjusted = !!(function(x, v) - enquo(v))(x, !!as.symbol(value_adjusted))) + add_tt_columns(.abundance_adjusted = !!(((function(x, v) enquo(v))(x,!!as.symbol(value_adjusted))) |> drop_enquo_env()) ) } @@ -1573,6 +1572,7 @@ setMethod("keep_variable", .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7) { @@ -1680,6 +1680,7 @@ setMethod("keep_variable", edgeR::filterByExpr( min.count = minimum_counts, group = string_factor_of_interest, + design = design, min.prop = minimum_proportion, lib.size = Matrix::colSums(., na.rm=TRUE) ) %>% @@ -1727,6 +1728,7 @@ setMethod("identify_abundant", .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7) { @@ -1746,7 +1748,8 @@ setMethod("identify_abundant", factor_of_interest = !!factor_of_interest, minimum_counts = minimum_counts, minimum_proportion = minimum_proportion, - .abundance = !!.abundance + .abundance = !!.abundance, + design = design ) .data[rowData(.data)$.abundant,] @@ -2819,14 +2822,14 @@ setMethod("describe_transcript", "RangedSummarizedExperiment", .describe_transcr #' @importFrom SummarizedExperiment as.data.frame .resolve_complete_confounders_of_non_interest <- function(se, ...){ - colData(se) = - colData(se) |> - as.data.frame() |> - .resolve_complete_confounders_of_non_interest_df(...) |> + colData(se) = + colData(se) |> + as.data.frame() |> + .resolve_complete_confounders_of_non_interest_df(...) |> DataFrame() - + se - + } #' resolve_complete_confounders_of_non_interest diff --git a/R/utilities.R b/R/utilities.R index 3f1dc2bb..c0f9f4e1 100755 --- a/R/utilities.R +++ b/R/utilities.R @@ -1514,3 +1514,31 @@ check_and_install_packages <- function(packages) { ) } } + +#' Drop Environment from a Quosure +#' +#' Takes a quosure and resets its environment to `emptyenv()` without altering +#' its expression. +#' +#' @param q A quosure object to have its environment stripped. +#' @return A quosure with the same expression but environment set to `emptyenv()`. +#' +#' @importFrom rlang is_quosure +#' @importFrom rlang quo_set_env +#' +#' @examples +#' library(rlang) +#' +#' q <- quo(x + y) +#' environment(q) +#' +#' q_stripped <- drop_enquo_env(q) +#' identical(quo_get_env(q_stripped), emptyenv()) # TRUE +#' +#' @noRd +drop_enquo_env <- function(q) { + if (!rlang::is_quosure(q)) { + stop("`q` must be a quosure.") + } + rlang::quo_set_env(q, emptyenv()) +} diff --git a/man/identify_abundant-methods.Rd b/man/identify_abundant-methods.Rd index 0bc9ba8d..2c31fbea 100644 --- a/man/identify_abundant-methods.Rd +++ b/man/identify_abundant-methods.Rd @@ -16,6 +16,7 @@ identify_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) @@ -26,6 +27,7 @@ identify_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) @@ -36,6 +38,7 @@ identify_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) @@ -46,6 +49,7 @@ identify_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) @@ -56,6 +60,7 @@ identify_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) @@ -66,6 +71,7 @@ identify_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) diff --git a/man/keep_abundant-methods.Rd b/man/keep_abundant-methods.Rd index efe98f34..ba92d824 100644 --- a/man/keep_abundant-methods.Rd +++ b/man/keep_abundant-methods.Rd @@ -16,6 +16,7 @@ keep_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) @@ -26,6 +27,7 @@ keep_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) @@ -36,6 +38,7 @@ keep_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) @@ -46,6 +49,7 @@ keep_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) @@ -56,6 +60,7 @@ keep_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) @@ -66,6 +71,7 @@ keep_abundant( .transcript = NULL, .abundance = NULL, factor_of_interest = NULL, + design = NULL, minimum_counts = 10, minimum_proportion = 0.7 ) diff --git a/man/resolve_complete_confounders_of_non_interest.Rd b/man/resolve_complete_confounders_of_non_interest.Rd index 01ad6808..9bfaa752 100644 --- a/man/resolve_complete_confounders_of_non_interest.Rd +++ b/man/resolve_complete_confounders_of_non_interest.Rd @@ -12,26 +12,26 @@ resolve_complete_confounders_of_non_interest(se, ...) \item{...}{Factors of non-interest (column names from `colData(se)`) to examine for complete confounders.} } \value{ -A `SummarizedExperiment` object with resolved confounders. The object retains its structure, including assays and metadata, +A `SummarizedExperiment` object with resolved confounders. The object retains its structure, including assays and metadata, but the column data (`colData`) is updated to reflect the resolved factors. } \description{ -This function identifies and resolves complete confounders among specified factors of non-interest within a `SummarizedExperiment` object. -Complete confounders occur when the levels of one factor are entirely predictable based on the levels of another factor. +This function identifies and resolves complete confounders among specified factors of non-interest within a `SummarizedExperiment` object. +Complete confounders occur when the levels of one factor are entirely predictable based on the levels of another factor. Such relationships can interfere with downstream analyses by introducing redundancy or collinearity. } \details{ -The function systematically examines pairs of specified factors and determines whether they are completely confounded. -If a pair of factors is found to be confounded, one of the factors is adjusted or removed to resolve the issue. +The function systematically examines pairs of specified factors and determines whether they are completely confounded. +If a pair of factors is found to be confounded, one of the factors is adjusted or removed to resolve the issue. The adjusted `SummarizedExperiment` object is returned, preserving all assays and metadata except the resolved factors. -Complete confounders of non-interest can create dependencies between variables that may bias statistical models or violate their assumptions. +Complete confounders of non-interest can create dependencies between variables that may bias statistical models or violate their assumptions. This function systematically addresses this by: 1. Identifying pairs of factors in the specified columns that are fully confounded. 2. Resolving confounding by adjusting or removing one of the factors from the `colData` slot. -The resolution strategy depends on the analysis context and can be modified in the helper function +The resolution strategy depends on the analysis context and can be modified in the helper function `resolve_complete_confounders_of_non_interest_pair_SE()`. By default, the function removes one of the confounded factors. } \examples{