diff --git a/DESCRIPTION b/DESCRIPTION index 31dcd942f3bb2a29681724c40d917ebc33b7c09a..b49b7f58b208529cab823bfceb4bceaee9c25bb5 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,12 +1,26 @@ Package: multiApply Title: Apply Functions to Multiple Multidimensional Arrays or Vectors -Version: 2.0.0 -Authors@R: c( +Version: 2.0.1 +Authors@R: c( person("BSC-CNS", role = c("aut", "cph")), person("Nicolau", "Manubens", , "nicolau.manubens@bsc.es", role = "aut"), person("Alasdair", "Hunter", , "alasdair.hunter@bsc.es", role = "aut"), person("Nuria", "Perez", , "nuria.perez@bsc.es", role = "cre")) -Description: The base apply function and its variants, as well as the related functions in the 'plyr' package, typically apply user-defined functions to a single argument (or a list of vectorized arguments in the case of mapply). The 'multiApply' package extends this paradigm with its only function, Apply, which efficiently applies functions taking one or a list of multiple unidimensional or multidimensional numeric arrays (or combinations thereof) as input. The input arrays can have different numbers of dimensions as well as different dimension lengths, and the applied function can return one or a list of unidimensional or multidimensional arrays as output. This saves development time by preventing the R user from writing often error-prone and memory-unefficient loops dealing with multiple complex arrays. Also, a remarkable feature of Apply is the transparent use of multi-core through its parameter 'ncores'. In contrast to the base apply function, this package suggests the use of 'target dimensions' as opposite to the 'margins' for specifying the dimensions relevant to the function to be applied. +Description: The base apply function and its variants, as well as the related + functions in the 'plyr' package, typically apply user-defined functions to a + single argument (or a list of vectorized arguments in the case of mapply). The + 'multiApply' package extends this paradigm with its only function, Apply, which + efficiently applies functions taking one or a list of multiple unidimensional + or multidimensional numeric arrays (or combinations thereof) as input. The input + arrays can have different numbers of dimensions as well as different dimension + lengths, and the applied function can return one or a list of unidimensional or + multidimensional arrays as output. This saves development time by preventing the + R user from writing often error-prone and memory-inefficient loops dealing with + multiple complex arrays. Also, a remarkable feature of Apply is the transparent + use of multi-core through its parameter 'ncores'. In contrast to the base apply + function, this package suggests the use of 'target dimensions' as opposite + to the 'margins' for specifying the dimensions relevant to the function to be + applied. Depends: R (>= 3.2.0) Imports: diff --git a/NAMESPACE b/NAMESPACE index 12eb9c50b1bb579c77ba3a41b70b37c9c3e783d5..ffae9459804741b68a08c0069a29b69ed0edabb1 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -5,3 +5,4 @@ importFrom(doParallel,registerDoParallel) importFrom(foreach,registerDoSEQ) importFrom(plyr,llply) importFrom(plyr,splat) +importFrom(utils,capture.output) diff --git a/R/Apply.R b/R/Apply.R index 876c8f44044be9e08af37690558f0ab878ac3caf..e130e9099858a6f61931f004e4c0de5d5966f037 100644 --- a/R/Apply.R +++ b/R/Apply.R @@ -29,6 +29,7 @@ #' @importFrom foreach registerDoSEQ #' @importFrom doParallel registerDoParallel #' @importFrom plyr splat llply +#' @importFrom utils capture.output Apply <- function(data, target_dims = NULL, fun, ..., output_dims = NULL, margins = NULL, guess_dim_names = TRUE, ncores = NULL, split_factor = 1) { @@ -527,8 +528,10 @@ Apply <- function(data, target_dims = NULL, fun, ..., if (!is.null(component_dims)) { atomic_fun_out_dims[[component]] <- component_dims } - sub_arrays_of_results[[component]][(1:prod(component_dims)) + - (n - 1) * prod(component_dims)] <- result[[component]] + if (length(result[[component]]) > 0) { + sub_arrays_of_results[[component]][(1:prod(component_dims)) + + (n - 1) * prod(component_dims)] <- result[[component]] + } } if (!found_first_sub_result) { found_first_sub_result <- TRUE diff --git a/README.md b/README.md index 99d3eab088df8157893d0ebba69966af6c8269aa..6258c1935af75f5d79423cef756e4190c3561fdf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -## multiApply [![build status](https://earth.bsc.es/gitlab/ces/multiApply/badges/master/build.svg)](https://earth.bsc.es/gitlab/ces/multiApply/commits/master) [![CRAN version](http://www.r-pkg.org/badges/version/multiApply)](https://cran.r-project.org/package=multiApply) [![coverage report](https://earth.bsc.es/gitlab/ces/multiApply/badges/master/coverage.svg)](https://earth.bsc.es/gitlab/ces/multiApply/commits/master) [![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0) [![CRAN RStudio Downloads](https://cranlogs.r-pkg.org/badges/multiApply)](https://cran.rstudio.com/web/packages/multiApply/index.html) +## multiApply [![build status](https://earth.bsc.es/gitlab/ces/multiApply/badges/master/build.svg)](https://earth.bsc.es/gitlab/ces/multiApply/commits/master) [![CRAN version](http://www.r-pkg.org/badges/version/multiApply)](https://cran.r-project.org/package=multiApply) [![coverage report](https://earth.bsc.es/gitlab/ces/multiApply/badges/master/coverage.svg)](https://earth.bsc.es/gitlab/ces/multiApply/commits/master) [![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0) [![CRAN RStudio Downloads](https://cranlogs.r-pkg.org/badges/multiApply)](https://cran.r-project.org/package=multiApply) -This package includes the function `Apply` as its only function. It extends the `apply` function to applications in which a function needs to be applied simultaneously over multiple input arrays. Although this can be done manually with for loops and calls to the base `apply` function, it can often be a challenging task which can easily result in error-prone or memory-unefficient code. +This package includes the function `Apply` as its only function. It extends the `apply` function to applications in which a function needs to be applied simultaneously over multiple input arrays. Although this can be done manually with for loops and calls to the base `apply` function, it can often be a challenging task which can easily result in error-prone or memory-inefficient code. A very simple example follows showing the kind of situation where `Apply` can be useful: imagine you have two arrays, each containing five 2x2 matrices, and you want to perform the multiplication of each of the five pairs of matrices. Next, one of the best ways to do this with base R (plus some helper libraries): diff --git a/multiApply-manual.pdf b/multiApply-manual.pdf index c1ab41cb14670fb7d596548390f3070814cc0963..8fabe141a52cc70c0e91997c670591579bd8489b 100644 Binary files a/multiApply-manual.pdf and b/multiApply-manual.pdf differ diff --git a/tests/testthat/test-use-cases.R b/tests/testthat/test-use-cases.R index 22aa8cad62affb72f0622a9a54c5db5fa933229a..2b27f5819ac279a0afccb28760af0a59293b62b4 100644 --- a/tests/testthat/test-use-cases.R +++ b/tests/testthat/test-use-cases.R @@ -1200,7 +1200,9 @@ test_that("in1: 2 dim; in2: 1 dim; targ. dims: 0-2, 0-1; out1: 1 dim; out2: 1 va # Real cases test_that("real use case - standardization", { standardization <- function(x, mean, deviation){ - (x - mean) / deviation + r <- (x - mean) / deviation + names(dim(r)) <- NULL + r } x <- array(1:(2*3*4), dim = c(mod = 2, lon = 3, lat = 4))