A suite of functions to subset or extract from (potentially complex) lists and list-like structures. Subsetting may occur according to certain data types, using identifier functions, element names or regular expressions to search the list for certain objects.
atomic_elem and list_elem are non-recursive functions to extract and replace the atomic and sub-list elements at the top-level of the list tree.
reg_elem is the recursive equivalent of atomic_elem and returns the 'regular' part of the list - with atomic elements in the final nodes. irreg_elem returns all the non-regular elements (i.e. call and terms objects, formulas, etc...). See Examples.
get_elem returns the part of the list responding to either an identifier function, regular expression, exact element names or indices applied to all final objects. has_elem checks for the existence of an element and returns TRUE if a match is found. See Examples.
## Non-recursive (top-level) subsetting and replacingatomic_elem(l, return ="sublist", keep.class =FALSE)atomic_elem(l)<- value
list_elem(l, return ="sublist", keep.class =FALSE)list_elem(l)<- value
## Recursive separation of regular (atomic) and irregular (non-atomic) partsreg_elem(l, recursive =TRUE, keep.tree =FALSE, keep.class =FALSE)irreg_elem(l, recursive =TRUE, keep.tree =FALSE, keep.class =FALSE)## Extract elements / subset list treeget_elem(l, elem, recursive =TRUE, DF.as.list =FALSE, keep.tree =FALSE, keep.class =FALSE, regex =FALSE, invert =FALSE,...)## Check for the existence of elementshas_elem(l, elem, recursive =TRUE, DF.as.list =FALSE, regex =FALSE,...)
Arguments
l: a list.
value: a list of the same length as the extracted subset of l.
elem: a function returning TRUE or FALSE when applied to elements of l, or a character vector of element names or regular expressions (if regex = TRUE). get_elem also supports a vector or indices which will be used to subset all final objects.
return: an integer or string specifying what the selector function should return. The options are:
Int.
String
Description
1
"sublist"
subset of list (default)
2
"names"
column names
3
"indices"
column indices
4
"named_indices"
named column indices
5
"logical"
logical selection vector
6
"named_logical"
named logical vector
Note: replacement functions only replace data, names are replaced together with the data.
recursive: logical. Should the list search be recursive (i.e. go though all the elements), or just at the top-level?
DF.as.list: logical. TRUE treats data frames like (sub-)lists; FALSE like atomic elements.
keep.tree: logical. TRUE always returns the entire list tree leading up to all matched results, while FALSE drops the top-level part of the tree if possible.
keep.class: logical. For list-based objects: should the class be retained? This only works if these objects have a [ method that retains the class.
regex: logical. Should regular expression search be used on the list names, or only exact matches?
invert: logical. Invert search i.e. exclude matched elements from the list?
...: further arguments to grep (if regex = TRUE).
Details
For a lack of better terminology, collapse defines 'regular' R objects as objects that are either atomic or a list. reg_elem with recursive = TRUE extracts the subset of the list tree leading up to atomic elements in the final nodes. This part of the list tree is unlistable - calling is_unlistable(reg_elem(l)) will be TRUE for all lists l. Conversely, all elements left behind by reg_elem will be picked up be irreg_elem. Thus is_unlistable(irreg_elem(l)) is always FALSE for lists with irregular elements (otherwise irreg_elem returns an empty list).
If keep.tree = TRUE, reg_elem, irreg_elem and get_elem always return the entire list tree, but cut off all of the branches not leading to the desired result. If keep.tree = FALSE, top-level parts of the tree are omitted as far as possible. For example in a nested list with three levels and one data-matrix in one of the final branches, get_elem(l, is.matrix, keep.tree = TRUE) will return a list (lres) of depth 3, from which the matrix can be accessed as lres[[1]][[1]][[1]]. This however does not make much sense. get_elem(l, is.matrix, keep.tree = FALSE) will therefore figgure out that it can drop the entire tree and return just the matrix. keep.tree = FALSE makes additional optimizations if matching elements are at far-apart corners in a nested structure, by only preserving the hierarchy if elements are above each other on the same branch. Thus for a list l <- list(list(2,list("a",1)),list(1,list("b",2))) calling get_elem(l, is.character) will just return list("a","b").