comprehension {eList} | R Documentation |
Vectorized Comprehension in R
Description
Functions that provide Python-style list (and related) comprehension.
Comprehensions convert for
loops into lapply
functions
before evaluation. Support for multiple variables, name assignment, nested loops,
custom iterators, if-else statements, and variety of return types included.
Usage
Comp(map = lapply, fun = NULL)
List(loop, clust = NULL, fun = NULL)
Env(loop, clust = NULL)
Vec(loop, clust = NULL, drop.names = FALSE)
Num(loop, clust = NULL, drop.names = FALSE)
Chr(loop, clust = NULL, drop.names = FALSE)
Logical(loop, clust = NULL, drop.names = FALSE)
Mat(loop, clust = NULL, by.col = TRUE)
DF(loop, clust = NULL)
Arguments
map |
function, such as |
fun |
function to be called on result after comprehension |
loop |
a |
clust |
cluster to use for |
drop.names |
logical; should names be dropped after conversion? Defaults to |
by.col |
should comprehension on matrix group by columns or rows? Defaults to |
Details
The comprehension functions parse an R loop expression into lapply
functions to allow for more readable code and easy creation and conversion
of vectors. The general syntax for a loop expression is as follows:
for (var in seq) <name=> <if (cond)> expr
where <...>
denotes optional statements. The seq
can be any R object:
a list, matrix, data.frame, environment, function, etc. The function iter
is called on the seq
. So the behavior can be easily described for custom
classes or objects. See helpers
for functions like zip
that can be used with seq
.
Multiple variables can be used in var
by separating the names with a period ".".
For example, i.j
is equivalent looping with variables i
and j
.
The downside is that periods cannot be used in the var
name. When multiple variables
are used, the object received from the sequence at each iteration is split and its
elements assigned in order to each of the variables. If the var
is i.j
and
the object received in the iteration was c(2,4,6)
, then i=2
, j=4
,
and 6 would not be assigned. Since variables are split on periods, i..j
could
be used to assign the first and third elements, or .i.j
the second and third.
Any number of variables can be used. Note that the entire object is returned if
there are no periods in the name, so use i..
if only the first object is needed.
To provide names within a loop, preface the expression with the desired name
for
that particular object followed by =
. name
can be any expression, just
make sure to surround any if
chain for the name with parentheses, or the R
parser will not detect that the assignment operator is associated with the expr
.
Behind the scenes, the expression on the left-hand side of "="
is wrapped in
an sapply
function and the results are assigned to the names
of the right-hand side result.
The if
statement can contain any number of if-else
statements and can
be nested. Similarly, for
statements can be nested any number of times and
converted to lapply
as long as the expression is a self-contained for
loop.
Though comprehensions are functions, both List(for ...)
and List[for ...]
syntax are supported. See ..
for a convenience wrapper around Vec
.
The different comprehensions primarily describe the return value, with List
return a "list" and Num
returning a numeric vector. If the object cannot be
converted, then an error will be produced. For Env
, the objects must be
named. This means that either the name must be assigned within the loop or the
loop is performed across a named object and the name is preserved. Another
difference is that is some comprehensions - though related to atomic vectors -
convert for
to sapply
while others convert to lapply
.
The Comp
function is used to create custom comprehensions. It should be
supplied with a map
function such as lapply
that
accepts arguments: X
for the argument over which the comprehension
iterates, FUN
a function applied to each element, and ...
for
additional arguments passed to the FUN
. Comp
also accepts a
post-evaluation function, fun
, that is applied to the result. This
could be used to ensure that the result complies to some class or other
restriction.
Users can also specify a cluster to use. If specified, then a parallel version
of lapply
or sapply
is used based on parLapply
and parSapply
from the parallel
package. This can greatly
reduce the calculation time for different operations, but has additional overhead
that makes the cost greater than the benefit for relatively small vectors. See
auto_cluster
for auto-creation.
Value
Determined by the function. List
returns an object of class 'list',
Num
returns a numeric vector, etc. See the descriptions of each function for
their return type.
Functions
-
Comp
: Create generalized comprehension function -
List
: Generate a 'list' from afor
loop -
Env
: Generate an 'environment' from afor
loop -
Vec
: Generate a flat, atomic 'vector' from afor
loop -
Num
: Generate a 'numeric' vector from afor
loop -
Chr
: Generate a 'character' vector from afor
loop -
Logical
: Generate a 'logical' vector from afor
loop -
Mat
: Generate a 'matrix' from afor
loop -
DF
: Generate a 'data.frame' from afor
loop
Examples
people <- list(
John = list(age = 30, weight = 180, mood = "happy", gender = "male"),
April = list(age = 26, weight = 110, mood = "sad", gender = "female"),
Jill = list(age = 42, weight = 125, mood = "ok", gender = "female")
)
weight_kg <- Num(for (i in people) i$weight/2.2)
gender <- Chr(for (i in people) i$gender)
gender_tab <- List(for (i in c("male", "female")) i = length(which(gender == i)))
Chr(for (..i.j in people) paste0(i, " & ", j))
Chr(for (i.j in items(people)) paste0(i, " is ", j$age, " years old."))
e <- Env(for (i.j in items(people)) i = j$age)
e$John
Num(for (i in 1:10) for (j in 2:6) if (i == j) i^2)