library(tinycodet)
#> Run `?tinycodet::tinycodet` to open the introduction help page of 'tinycodet'.
source_selection
The source_selection()
function is the same as base R’s
source()
function, except that it allows only placing the
selected objects and functions into the current environment, instead of
all objects.
The objects to be selected can be specified using any combination of the following:
- by supplying a character vector of exact object names to the
select
argument. - by supplying a character vector of
regex
patterns to theregex
argument. - by supplying a character vector of
fixed
patterns to thefixed
argument.
The regex
and fixed
arguments are
especially handy when sourcing S3 methods. For example, to expose the
following methods to the current environment,
mymethod.numeric()
and mymethod.character()
from generic mymethod()
, one could specify
regex = "^mymethod"
.
Example:
exprs <- expression({
helloworld = function()print("helloworld")
goodbyeworld <- function() print("goodbye world")
`%s+test%` <- function(x,y) stringi::`%s+%`(x,y)
`%s*test%` <- function(x,y) stringi::`%s*%`(x,y)
mymethod <- function(x) UseMethod("mymethod", x)
mymethod.numeric <- function(x)x * 2
mymethod.character <- function(x)chartr(x, old = "a-zA-Z", new = "A-Za-z")
})
temp.fun <- function(){
source_selection(list(exprs=exprs), regex= "^mymethod", fixed = c("%", ":="))
ls() # list all objects residing within the function definition
}
temp.fun()
#> Sourcing script ...
#> Done
#> [1] "%s*test%" "%s+test%" "mymethod"
#> [4] "mymethod.character" "mymethod.numeric"
temp.fun <- function(){
source_selection(list(exprs=exprs), select = c("helloworld", "goodbyeworld"))
ls() # list all objects residing within the function definition
}
temp.fun()
#> Sourcing script ...
#>
#> Done
#> [1] "goodbyeworld" "helloworld"
Matrix re-ordering operators
The tinycodet
R package adds 2 additional matrix
operators:
- The
x %row~% mat
operator re-orders the elements of every row, each row ordered independently from the other rows, of matrixx
, by the ordering ranks given in matrixmat
. - The
x %col~% mat
operator re-orders the elements of every column, each column ordered independently from the other columns, of matrixx
, by the ordering ranks given in matrixmat
.
If matrix x
is a numeric matrix, and one wants to
numerically sort the elements of every row or column,
x %row~% x
or x %col~% x
would suffice,
respectively.
If matrix x
is not numeric, sorting using
x %row~% x
and x %col~% x
is still possible,
but probably not the best option. In the non-numeric case, providing a
matrix of ordering ranks would probably be faster and give more accurate
ordering.
If mat
is a matrix of non-repeating random integers
(i.e. sample(1:length(x), replace=FALSE)
),
x %row~% mat
will randomly shuffle the elements of every
row, where the shuffling order in each row is independent from the
shuffling order in the other rows. Similarly, x %col~% mat
will randomly shuffle the elements of every column, where the shuffling
order in each column is independent from the shuffling order in the
other columns.
Re-ordering/sorting every row/column of a matrix with these operators is generally faster than doing so through loops.
Examples with a numeric matrix:
x <- matrix(sample(1:25), nrow=5)
print(x)
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 13 15 22 14 25
#> [2,] 23 20 19 10 11
#> [3,] 12 4 8 18 17
#> [4,] 5 21 2 16 1
#> [5,] 6 9 7 24 3
x %row~% x # sort elements of every row
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 13 14 15 22 25
#> [2,] 10 11 19 20 23
#> [3,] 4 8 12 17 18
#> [4,] 1 2 5 16 21
#> [5,] 3 6 7 9 24
x %row~% -x # reverse-sort elements of every row
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 25 22 15 14 13
#> [2,] 23 20 19 11 10
#> [3,] 18 17 12 8 4
#> [4,] 21 16 5 2 1
#> [5,] 24 9 7 6 3
x %col~% x # sort elements of every column
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 5 4 2 10 1
#> [2,] 6 9 7 14 3
#> [3,] 12 15 8 16 11
#> [4,] 13 20 19 18 17
#> [5,] 23 21 22 24 25
x %col~% -x # reverse-sort elements of every column
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 23 21 22 24 25
#> [2,] 13 20 19 18 17
#> [3,] 12 15 8 16 11
#> [4,] 6 9 7 14 3
#> [5,] 5 4 2 10 1
x <- matrix(sample(1:25), nrow=5)
print(x)
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 22 9 8 3 5
#> [2,] 11 10 25 13 16
#> [3,] 7 2 1 20 15
#> [4,] 21 17 14 23 12
#> [5,] 6 4 18 24 19
rand <- sample(1:length(x)) |> matrix(ncol=ncol(x)) # matrix of random integers
x %row~% rand # random shuffle every row independent of other rows
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 8 3 9 5 22
#> [2,] 25 11 13 10 16
#> [3,] 2 20 7 1 15
#> [4,] 21 17 12 14 23
#> [5,] 6 19 24 4 18
x %col~% rand # random shuffle every column independent of other columns
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 6 17 8 20 12
#> [2,] 21 2 25 3 19
#> [3,] 7 9 14 23 5
#> [4,] 11 4 1 24 16
#> [5,] 22 10 18 13 15
Examples with a character matrix:
x <- matrix(sample(letters, 25), nrow=5)
print(x)
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] "b" "n" "t" "r" "k"
#> [2,] "f" "e" "a" "z" "d"
#> [3,] "g" "x" "m" "p" "h"
#> [4,] "l" "w" "y" "s" "i"
#> [5,] "v" "q" "o" "c" "j"
mat <- stringi::stri_rank(as.vector(x)) |>
matrix(ncol=ncol(x)) # matrix of ordering ranks
x %row~% mat # sort elements of every row
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] "b" "k" "n" "r" "t"
#> [2,] "a" "d" "e" "f" "z"
#> [3,] "g" "h" "m" "p" "x"
#> [4,] "i" "l" "s" "w" "y"
#> [5,] "c" "j" "o" "q" "v"
x %row~% -mat # reverse-sort elements of every row
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] "t" "r" "n" "k" "b"
#> [2,] "z" "f" "e" "d" "a"
#> [3,] "x" "p" "m" "h" "g"
#> [4,] "y" "w" "s" "l" "i"
#> [5,] "v" "q" "o" "j" "c"
x %col~% mat # sort elements of every column
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] "b" "e" "a" "c" "d"
#> [2,] "f" "n" "m" "p" "h"
#> [3,] "g" "q" "o" "r" "i"
#> [4,] "l" "w" "t" "s" "j"
#> [5,] "v" "x" "y" "z" "k"
x %col~% -mat # reverse-sort elements of every column
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] "v" "x" "y" "z" "k"
#> [2,] "l" "w" "t" "s" "j"
#> [3,] "g" "q" "o" "r" "i"
#> [4,] "f" "n" "m" "p" "h"
#> [5,] "b" "e" "a" "c" "d"
x <- matrix(sample(letters, 25), nrow=5)
print(x)
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] "b" "f" "z" "p" "l"
#> [2,] "h" "m" "g" "v" "o"
#> [3,] "i" "t" "d" "q" "y"
#> [4,] "s" "c" "k" "u" "a"
#> [5,] "x" "w" "n" "r" "j"
rand <- sample(1:length(x)) |> matrix(ncol=ncol(x)) # matrix of random integers
x %row~% rand # random shuffle every row independent of other rows
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] "f" "z" "l" "p" "b"
#> [2,] "m" "v" "g" "h" "o"
#> [3,] "y" "t" "q" "i" "d"
#> [4,] "a" "s" "k" "c" "u"
#> [5,] "n" "w" "r" "x" "j"
x %col~% rand # random shuffle every column independent of other columns
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] "s" "m" "z" "v" "y"
#> [2,] "b" "t" "g" "p" "a"
#> [3,] "h" "f" "n" "q" "l"
#> [4,] "i" "w" "k" "r" "o"
#> [5,] "x" "c" "d" "u" "j"
Because each row/column is re-ordered independently of all other
columns, it would be deceptive to keep the row- and column-names, as
they no longer hold. Thus, for consistency, these operators strip all
attributes from the input matrix x
.
Additional logic operators
The tinycodet package adds a few basic logic operators:
-
%xor%
: Exclusive OR -
%n&%
: NOT AND (i.e.(!x) & (!y)
). Note that if eitherx
ory
isNA
,%n&%
will also giveNA
(unlike(!x) & (!y)
, which would giveFALSE
.) -
%?=%
: checks if bothx
andy
are unknown or unreal (NA, NaN, Inf, -Inf) -
%out%
: the opposite of%in%
(i.e.!x %in% y
)
Here are some examples:
x <- c(TRUE, FALSE, TRUE, FALSE, NA, NaN, Inf, -Inf, TRUE, FALSE)
y <- c(FALSE, TRUE, TRUE, FALSE, rep(NA, 6))
outcome <- data.frame(
x=x, y=y,
"x %xor% y"=x %xor% y, "x %n&% y" = x %n&% y, "x %?=% y" = x %?=% y,
check.names = FALSE
)
knitr::kable(outcome)
x | y | x %xor% y | x %n&% y | x %?=% y |
---|---|---|---|---|
1 | FALSE | TRUE | FALSE | FALSE |
0 | TRUE | TRUE | FALSE | FALSE |
1 | TRUE | FALSE | FALSE | FALSE |
0 | FALSE | FALSE | TRUE | FALSE |
NA | NA | NA | NA | TRUE |
NaN | NA | NA | NA | TRUE |
Inf | NA | NA | NA | TRUE |
-Inf | NA | NA | NA | TRUE |
1 | NA | NA | NA | FALSE |
0 | NA | NA | NA | FALSE |
1:3 %out% 1:10
#> [1] FALSE FALSE FALSE
1:10 %out% 1:3
#> [1] FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
Numbers can have many different sub-types whilst still being
numeric
. The n %=numtype% numtype
operator
will check for every value of numeric vector n
if it can be
considered a number belonging to type numtype
. The
following values for numtype
are allowed:
- “~0”: zero, or else a number whose absolute value is smaller than
the Machine tolerance (
sqrt(.Machine$double.eps)
); - “B”: binary numbers (0 or 1);
- “prop”: proportions;
- “I”: Integers;
- “odd”: odd integers;
- “even”: even integers
- “R”: Real numbers;
- “unreal”: infinity, NA, or NaN;
The string counterpart for %=numtype%
is
s %=strtype% strtype
, which checks for every value of
character vector s
if it can seen as a certain
strtype
. The following values for strtype
are
allowed:
- “empty”: checks if the string only consists of empty spaces.
- “unreal”: checks if the string is NA, or if it has literal string “NA”, “NaN” or “Inf”, regardless if it has leading or trailing spaces.
- “numeric”: checks if the string can be converted to a number, disregarding leading and trailing spaces. I.e. the string “5.0” can be converted to the the actual number 5.0.
- “special”: checks if the string consists of only special characters.
Here are some examples:
1e-20 %=numtype% "~0"
#> [1] TRUE
n <- c(0:5, 0:-5, 0.1, -0.1, 0, 1, Inf, -Inf, NA, NaN)
n[n %=numtype% "B"]
#> [1] 0 1 0 0 1
n[n %=numtype% "prop"]
#> [1] 0.0 1.0 0.0 0.1 0.0 1.0
n[n %=numtype% "B"]
#> [1] 0 1 0 0 1
n[n %=numtype% "I"]
#> [1] 0 1 2 3 4 5 0 -1 -2 -3 -4 -5 0 1
n[n %=numtype% "odd"]
#> [1] 1 3 5 -1 -3 -5 1
n[n %=numtype% "even"]
#> [1] 0 2 4 0 -2 -4 0
n[n %=numtype% "R"]
#> [1] 0.0 1.0 2.0 3.0 4.0 5.0 0.0 -1.0 -2.0 -3.0 -4.0 -5.0 0.1 -0.1 0.0
#> [16] 1.0
n[n %=numtype% "unreal"]
#> [1] Inf -Inf NA NaN
s <- c(" AbcZ123 ", " abc ", " 1.3 ", " !#$%^&*() ", " ", " NA ", " NaN ", " Inf ")
s[s %=strtype% "empty"]
#> [1] " "
s[s %=strtype% "unreal"]
#> [1] " NA " " NaN " " Inf "
s[s %=strtype% "numeric"]
#> [1] " 1.3 " " Inf "
s[s %=strtype% "special"]
#> [1] " !#$%^&*() "