Writing Custom Functions for `matsbyname`
Matthew Kuperus Heun
2024-02-12
Source:vignettes/applybyname-vignette.Rmd
applybyname-vignette.Rmd
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 directly to output (the default) |
"transpose" |
rowtype of becomes coltype of output; coltype of becomes rowtype of output |
"row" |
rowtype of becomes both rowtype and coltype of output |
"col" |
coltype of becomes both rowtype and coltype of output |
"none" |
rowtype and coltype not set by this function; will set rowtype and coltype |
A simple example follows.
U <- matrix(1:4, ncol = 2, dimnames = list(c("p1", "p2"), c("i1", "i2"))) %>%
setrowtype("Products") %>% setcoltype("Industries")
U
## i1 i2
## p1 1 3
## p2 2 4
## attr(,"rowtype")
## [1] "Products"
## attr(,"coltype")
## [1] "Industries"
difference_byname(0, U)
## i1 i2
## p1 -1 -3
## p2 -2 -4
## attr(,"rowtype")
## [1] "Products"
## attr(,"coltype")
## [1] "Industries"
unaryapply_byname(`-`, U)
## i1 i2
## p1 -1 -3
## p2 -2 -4
## attr(,"rowtype")
## [1] "Products"
## attr(,"coltype")
## [1] "Industries"
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.
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
## c1 c2
## r1 1 3
## r2 2 4
## attr(,"rowtype")
## [1] "row"
## attr(,"coltype")
## [1] "col"
elementapply_byname(divide, a = m, row = 1, col = 1, .FUNdots = list(divisor = 2))
## c1 c2
## r1 0.5 3
## r2 2.0 4
## attr(,"rowtype")
## [1] "row"
## attr(,"coltype")
## [1] "col"
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.
U <- matrix(1:4, ncol = 2, dimnames = list(c("p1", "p2"), c("i1", "i2"))) %>%
setrowtype("Products") %>% setcoltype("Industries")
U
## i1 i2
## p1 1 3
## p2 2 4
## attr(,"rowtype")
## [1] "Products"
## attr(,"coltype")
## [1] "Industries"
Y <- matrix(1:4, ncol = 2, dimnames = list(c("p2", "p1"), c("i2", "i1"))) %>%
setrowtype("Products") %>% setcoltype("Industries")
Y
## i2 i1
## p2 1 3
## p1 2 4
## attr(,"rowtype")
## [1] "Products"
## attr(,"coltype")
## [1] "Industries"
sum_byname(U, Y)
## i1 i2
## p1 5 5
## p2 5 5
## attr(,"rowtype")
## [1] "Products"
## attr(,"coltype")
## [1] "Industries"
binaryapply_byname(`+`, U, Y)
## i1 i2
## p1 5 5
## p2 5 5
## attr(,"rowtype")
## [1] "Products"
## attr(,"coltype")
## [1] "Industries"
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.
cumapply_byname(sum_byname, list(1, 2, 3, 4))
## [[1]]
## [1] 1
##
## [[2]]
## [1] 3
##
## [[3]]
## [1] 6
##
## [[4]]
## [1] 10
cumapply_byname(hadamardproduct_byname, list(1, 2, 3, 4))
## [[1]]
## [1] 1
##
## [[2]]
## [1] 2
##
## [[3]]
## [1] 6
##
## [[4]]
## [1] 24
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!