From 44a567c58e92e7597e80864f125e101400a32ffb Mon Sep 17 00:00:00 2001 From: vagudets Date: Mon, 23 Jun 2025 12:27:26 +0200 Subject: [PATCH 1/3] Add list names in documentation for 'target_dims' and 'margins' --- R/Apply.R | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/R/Apply.R b/R/Apply.R index 54841d3..55afc40 100644 --- a/R/Apply.R +++ b/R/Apply.R @@ -38,8 +38,9 @@ #' order than the provided, \code{Apply} will automatically reorder the #' dimensions as needed. #'@param target_dims One or a list of vectors (or NULLs) containing the -#' dimensions to be input into fun for each of the objects in the data. If a -#' single vector of target dimensions is specified and multiple inputs are +#' dimensions to be input into fun for each of the objects in the data. +#' The list of vectors can be named in the same way as 'data'. If a +# single vector of target dimensions is specified and multiple inputs are #' provided in 'data, then the single set of target dimensions is re-used for #' all of the inputs. These vectors can contain either integers specifying the #' position of the dimensions, or character strings corresponding to the @@ -69,7 +70,8 @@ #' dimensions to be output from the fun for each of the objects it returns (or #' a single vector if the function has only one output). #'@param margins One or a list of vectors (or NULLs) containing the 'margin' -#' dimensions to be looped over for each input in 'data'. If a single vector of +#' dimensions to be looped over for each input in 'data'. The list of vectors +#' list can be named in the same way as 'data'. If a single vector of #' margins is specified and multiple inputs are provided in 'data', then the #' single set of margins is re-used for all of the inputs. These vectors can #' contain either integers specifying the position of the margins, or character @@ -133,7 +135,7 @@ #' data <- list(x = array(rnorm(50), c(5, 10)), #' array(rnorm(500), c(5, 10)), #' array(rnorm(50), c(5, 10))) -#' test <- Apply(data, target_dims = list(1, 1, 1), test_fun) +#' test <- Apply(data, target_dims = list(x = 1, 1, 1), test_fun) #' #'@importFrom foreach registerDoSEQ #'@importFrom doParallel registerDoParallel @@ -276,6 +278,24 @@ Apply <- function(data, target_dims = NULL, fun, ..., if (!is.list(margins)) { margins <- rep(list(margins), length(data)) } + if (!is.null(names(margins)) && !is.null(formalArgs(fun))) { + fun_args <- formalArgs(fun) + if (!all(names(margins)[which(names(margins) != "")] %in% fun_args)) { + stop("Some names in 'margins' are not found as arguments in 'fun'. ", + "Please rename the elements to match the 'fun' argument names, ", + "or provide an unnamed list in the expected order.") + } + unnamed_elements <- which(names(data) == "") + common_args <- fun_args[which(fun_args %in% names(margins))] + common_args <- match(common_args, names(margins)) + margins <- margins[c(common_args, unnamed_elements)] + if (length(unnamed_elements) > 0) { + warning("Some elements in list 'margins' are named, while others are ", + "unnamed. The unnamed elements have been placed at the end of ", + "the list. Please check carefully that the order is the same ", + "as expected by 'fun', or provide list names for safety.") + } + } if (any(!sapply(margins, function(x) is.character(x) || is.numeric(x) || is.null(x)))) { stop("Parameter 'margins' must be one or a list of numeric or ", @@ -343,6 +363,24 @@ Apply <- function(data, target_dims = NULL, fun, ..., if (any(sapply(target_dims, function(x) is.character(x) && (length(x) == 0)))) { stop("Parameter 'target_dims' must not contain length-0 character vectors.") } + if (!is.null(names(target_dims)) && !is.null(formalArgs(fun))) { + fun_args <- formalArgs(fun) + if (!all(names(target_dims)[which(names(target_dims) != "")] %in% fun_args)) { + stop("Some names in 'target_dims' are not found as arguments in 'fun'. ", + "Please rename the elements to match the 'fun' argument names, ", + "or provide an unnamed list in the expected order.") + } + unnamed_elements <- which(names(data) == "") + common_args <- fun_args[which(fun_args %in% names(target_dims))] + common_args <- match(common_args, names(target_dims)) + target_dims <- target_dims[c(common_args, unnamed_elements)] + if (length(unnamed_elements) > 0) { + warning("Some elements in list 'target_dims' are named, while others are ", + "unnamed. The unnamed elements have been placed at the end of ", + "the list. Please check carefully that the order is the same ", + "as expected by 'fun', or provide list names for safety.") + } + } duplicate_dim_specs <- sapply(target_dims, function(x) { length(unique(x)) != length(x) -- GitLab From 376188482feb1e5cf4d29b8b9732de19c34b5d5e Mon Sep 17 00:00:00 2001 From: vagudets Date: Mon, 23 Jun 2025 12:35:48 +0200 Subject: [PATCH 2/3] Update .Rd file --- man/Apply.Rd | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/man/Apply.Rd b/man/Apply.Rd index 9e8ccd6..14ce265 100644 --- a/man/Apply.Rd +++ b/man/Apply.Rd @@ -29,8 +29,8 @@ order than the provided, \code{Apply} will automatically reorder the dimensions as needed.} \item{target_dims}{One or a list of vectors (or NULLs) containing the -dimensions to be input into fun for each of the objects in the data. If a -single vector of target dimensions is specified and multiple inputs are +dimensions to be input into fun for each of the objects in the data. +The list of vectors can be named in the same way as 'data'. If a provided in 'data, then the single set of target dimensions is re-used for all of the inputs. These vectors can contain either integers specifying the position of the dimensions, or character strings corresponding to the @@ -64,7 +64,8 @@ dimensions to be output from the fun for each of the objects it returns (or a single vector if the function has only one output).} \item{margins}{One or a list of vectors (or NULLs) containing the 'margin' -dimensions to be looped over for each input in 'data'. If a single vector of +dimensions to be looped over for each input in 'data'. The list of vectors +list can be named in the same way as 'data'. If a single vector of margins is specified and multiple inputs are provided in 'data', then the single set of margins is re-used for all of the inputs. These vectors can contain either integers specifying the position of the margins, or character @@ -164,7 +165,7 @@ test_fun <- function(x, ...) { data <- list(x = array(rnorm(50), c(5, 10)), array(rnorm(500), c(5, 10)), array(rnorm(50), c(5, 10))) -test <- Apply(data, target_dims = list(1, 1, 1), test_fun) +test <- Apply(data, target_dims = list(x = 1, 1, 1), test_fun) } \references{ -- GitLab From 3afea9343d81600de7351345eb9d0b2dd8aac35a Mon Sep 17 00:00:00 2001 From: vagudets Date: Wed, 25 Jun 2025 08:45:39 +0200 Subject: [PATCH 3/3] Bugfix: margins and target_dim names --- R/Apply.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/Apply.R b/R/Apply.R index 55afc40..8ebdd4d 100644 --- a/R/Apply.R +++ b/R/Apply.R @@ -285,7 +285,7 @@ Apply <- function(data, target_dims = NULL, fun, ..., "Please rename the elements to match the 'fun' argument names, ", "or provide an unnamed list in the expected order.") } - unnamed_elements <- which(names(data) == "") + unnamed_elements <- which(names(margins) == "") common_args <- fun_args[which(fun_args %in% names(margins))] common_args <- match(common_args, names(margins)) margins <- margins[c(common_args, unnamed_elements)] @@ -370,7 +370,7 @@ Apply <- function(data, target_dims = NULL, fun, ..., "Please rename the elements to match the 'fun' argument names, ", "or provide an unnamed list in the expected order.") } - unnamed_elements <- which(names(data) == "") + unnamed_elements <- which(names(target_dims) == "") common_args <- fun_args[which(fun_args %in% names(target_dims))] common_args <- match(common_args, names(target_dims)) target_dims <- target_dims[c(common_args, unnamed_elements)] -- GitLab