To cite the frab
package in publications please use
Hankin (2023). The frab
package allows one to “add” R
tables in a natural way. It also furnishes an alternative interpretation
of named vectors wherein addition is defined using the (unique) names as
the primary key. Support for multi-dimensional R tables is included. The
underlying mathematical object is the Free Abelian group.
The package has two S4 classes: frab
and
sparsetable
. Class frab
is for one-dimensional
R tables and is an alternative implementation of named vectors; class
sparsetable
handles multi-way R tables in a natural
way.
frab
Primary construction function frab()
takes a named
vector and returns a frab
object:
suppressMessages(library("frab"))
<- c(x=1,b=2,a=2,b=3,c=7,x=-1)
p frab(p)
#> A frab object with entries
#> a b c
#> 2 5 7
Above, we see from the return value that function frab()
has reordered the labels of its argument, calculated the value for entry
b
[as
p#> x b a b c x
#> 1 2 2 3 7 -1
Above we see p
might correspond to a story: “look, we
have one x
, two b
s, two a
s,
another three b
s, seven c
s…oh hang on that
x
was a mistake I had better subtract one now”. However,
the package’s most useful feature is the overloaded definition of
addition:
<- rfrab())
(x #> A frab object with entries
#> a b c d g i
#> 3 6 1 5 7 5
<- rfrab())
(y #> A frab object with entries
#> a b c d e f i
#> 4 4 1 1 8 5 2
+y
x#> A frab object with entries
#> a b c d e f g i
#> 7 10 2 6 8 5 7 7
Above we see function rfrab()
used to generate a random
frab
object, corresponding to an R table. It is
possible to add x
and y
directly:
<- as.namedvector(x)
xn <- as.namedvector(y)
yn table(c(rep(names(xn),times=xn),rep(names(yn),times=yn)))
#>
#> a b c d e f g i
#> 7 10 2 6 8 5 7 7
but this is extremely inefficient and cannot deal with fractional (or indeed negative) entries.
Class sparsetable
deals with multi-way R tables. Taking
three-way R tables as an example:
<- rspar())
(x3 #> Jan Feb Mar val
#> a a a = 10
#> a c b = 15
#> b a a = 11
#> b a b = 9
#> b a c = 12
#> b b a = 6
#> b b b = 3
#> b b c = 14
#> b c a = 9
#> b c c = 21
#> c c a = 10
Function rspar()
returns a random
sparsetable
object. We see that, of the
as.array(x3)
#> , , Mar = a
#>
#> Feb
#> Jan a b c
#> a 10 0 0
#> b 11 6 9
#> c 0 0 10
#>
#> , , Mar = b
#>
#> Feb
#> Jan a b c
#> a 0 0 15
#> b 9 3 0
#> c 0 0 0
#>
#> , , Mar = c
#>
#> Feb
#> Jan a b c
#> a 0 0 0
#> b 12 14 21
#> c 0 0 0
In this case it is hardly worth taking advantage of the sparse
representation (which is largely inherited from the spray
package) but a larger example might be
rspar(n=4,l=10,d=12)
#> Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec val
#> b c j e f j f a g i a d = 1
#> g a j e c f e c a f g c = 4
#> j b j g h c d c c b b i = 2
#> j j h h a a i f c h g h = 3
The random sparsetable
object shown above would require
<- rspar()
y3 +y3
x3#> Jan Feb Mar val
#> a a a = 10
#> a a b = 14
#> a b a = 4
#> a c a = 14
#> a c b = 15
#> b a a = 11
#> b a b = 23
#> b a c = 12
#> b b a = 17
#> b b b = 13
#> b b c = 23
#> b c a = 9
#> b c b = 7
#> b c c = 24
#> c a a = 15
#> c c a = 15
#> c c c = 14
Two-way R tables are something of a special case, having their own
print method. By default, two-dimensional sparsetable
objects are coerced to a matrix before printing, but otherwise operate
in the same way as the multi-dimensional case discussed above:
<- rspar2())
(x2 #> bar
#> foo A B D E F
#> a 3 20 0 0 9
#> b 0 0 15 0 0
#> c 0 0 0 4 0
#> d 0 0 0 5 22
#> e 0 2 0 11 29
<- rspar2())
(y2 #> bar
#> foo A C D E F
#> a 9 0 25 6 10
#> b 7 0 0 0 1
#> c 0 0 0 11 0
#> d 8 5 0 4 0
#> e 0 3 2 0 0
#> f 0 0 14 0 15
+y2
x2#> bar
#> foo A B C D E F
#> a 12 20 0 25 6 19
#> b 7 0 0 15 0 1
#> c 0 0 0 0 15 0
#> d 8 0 5 0 9 22
#> e 0 2 3 2 11 29
#> f 0 0 0 14 0 15
Above, note how the sizes of the coerced matrices are different (
For more detail, see the package vignette
vignette("frab")
R
: the
frab
package”, arXiv, https://arxiv.org/abs/2307.13184.R
:
introducing the disordR
package”, arXiv, https://arxiv.org/abs/2210.03856