--- title: "Writing Custom Functions for `matsbyname`" author: "Matthew Kuperus Heun" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: smart: false vignette: > %\VignetteIndexEntry{Writing Custom Functions for `matsbyname`} %\VignetteEngine{knitr::rmarkdown} \usepackage[utf8]{inputenc} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) library(dplyr) library(matsbyname) ``` ## Introduction The `matsbyname` package provides many useful functions for \"by name\" manipulation of matrices, lists of matrices, and matrices in columns of data frames. However, the built-in functions may not cover all possible needs. `matsbyname` provides three functions for these situations: | Function | Purpose |--:|:------------------------------------ | `unaryapply_byname` | apply a unary function to a single matrix, a list of matrices, or a column of matrices in a data frame | `elementapply_byname` | apply a unary function to a single element of a matrix or a column of matrices in a data frame | `binaryapply_byname` | apply a binary function to two matrices or Map a binary function across two lists of matrices or two columns of matrices in a data frame | `cumapply_byname` | apply a binary function cumulatively to a single list of matrices or a column of matrices in a data frame ## How the `*apply_byname` functions work The `*apply_byname` functions have several arguments. | Argument | Description |--:|:------------------------------ `FUN` | a unary function in the case of `unaryapply_byname`, a binary function (that may also accept a single argument) in the case of `binaryapply_byname`, and a binary function (that must also accept only a single argument) in the case of `cumapply_byname` `a` | a matrix, a list or matrices, or a column of matrices in a data frame `b` | a matrix, a list or matrices, or a column of matrices in a data frame `.FUNdots` | a named list of arguments to be passed to `FUN` `rowcoltypes` | tells what to do with row and column types `match_type` | tells how row and column types of `a` and `b` arguments must be matched `.organize` | tells whether to automatically complete `a` and `b` relative to each other and sort the rows and columns of the completed matrices `FUN` is mapped as expected over `a` (in the case of `unaryapply_byname`, `elementapply_byname`, and `cumapply_byname`) or over `a` and `b` (in the case of `binaryapply_byname`). `FUN` should assume that its `a` and/or `b` arguments are single numbers or matrices; `*apply_byname` handles all mapping across lists. The following sections describe each `*apply_byname` function. ## `unaryapply_byname` `unaryapply_byname` applies `FUN` to a single matrix, a list of matrices, or (if used with `dplyr::mutate()`) a column in a data frame that contains matrices. The `rowcoltypes` argument must be one of the following: | `rowcoltypes` value | Behaviour |--:|:--------------------------------- `"all"` | transfer both row and column types of \code{a} directly to output (the default) `"transpose"` | rowtype of \code{a} becomes coltype of output; coltype of \code{a} becomes rowtype of output `"row"` | rowtype of \code{a} becomes both rowtype and coltype of output `"col"` | coltype of \code{a} becomes both rowtype and coltype of output `"none"` | rowtype and coltype not set by this function; \code{FUN} will set rowtype and coltype A simple example follows. ```{r} U <- matrix(1:4, ncol = 2, dimnames = list(c("p1", "p2"), c("i1", "i2"))) %>% setrowtype("Products") %>% setcoltype("Industries") U difference_byname(0, U) unaryapply_byname(`-`, U) ``` ## `elementapply_byname` `elementapply_byname` applies `FUN` to a single matrix, a list of matrices, or (if used with `dplyr::mutate()`) a column in a data frame that contains matrices. A simple example follows. ```{r} divide <- function(x, divisor){ x/divisor } m <- matrix(c(1:4), nrow = 2, ncol = 2, dimnames = list(c("r1", "r2"), c("c1", "c2"))) %>% setrowtype("row") %>% setcoltype("col") m elementapply_byname(divide, a = m, row = 1, col = 1, .FUNdots = list(divisor = 2)) ``` ## `binaryapply_byname` `binaryapply_byname` applies `FUN` to a pair of matrices, a pair of lists of matrices, or (if used with `dplyr::mutate`) a pair of columns in a data frame that contains matrices. `match_type` must be one of `"all"`, `"matmult"`, or `"none"`. | `match_type` value | Behaviour |--:|:-------------------------------------------- `"all"` | rowtypes of `a` must match rowtypes of `b` and coltypes of `a` must match coltypes of `b` (the default) `"matmult"` | coltypes of `a` must match rowtypes of `b` `"none"` | neither coltypes nor rowtypes are checked The `rowcoltypes` argument (a boolean) tells whether to apply row and column types from `a` and `b` to the output. The `.organize` argument (a boolean) tells whether to automatically complete `a` and `b` relative to each other and sort the rows and columns of the completed matrices. Normally, this should be `TRUE` (the default). A simple example follows. ```{r} U <- matrix(1:4, ncol = 2, dimnames = list(c("p1", "p2"), c("i1", "i2"))) %>% setrowtype("Products") %>% setcoltype("Industries") U Y <- matrix(1:4, ncol = 2, dimnames = list(c("p2", "p1"), c("i2", "i1"))) %>% setrowtype("Products") %>% setcoltype("Industries") Y sum_byname(U, Y) binaryapply_byname(`+`, U, Y) ``` ## `cumapply_byname` `cumapply_byname` applies `FUN` cumulatively to a list of numbers, a list of matrices, or (if used with `dplyr::mutate`) a column of a data frame. `FUN` must be a binary function that also allows a single argument. The result is a list with first element `FUN(m[[1]])`. For `i >= 2`, elements of the resulting list are `FUN(m[[i]], out[[i-1]])`, where `out` is the result list. Simple examples follow. ```{r} cumapply_byname(sum_byname, list(1, 2, 3, 4)) cumapply_byname(hadamardproduct_byname, list(1, 2, 3, 4)) ``` ## Summary The various `*apply_byname` functions allow users to extend the functionality of the `matsbyname` package as needed for any problem domain. The functions are used extensively in `matsbyname` itself. In fact, all `matsbyname` functions utilize the `*apply_byname` functions, so they are ready for prime time!