Find and Extract / Subset List Elements
extract_list.Rd
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
andlist_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 ofatomic_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 returnsTRUE
if a match is found. See Examples.
Usage
## Non-recursive (top-level) subsetting and replacing
atomic_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) parts
reg_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 tree
get_elem(l, elem, recursive = TRUE, DF.as.list = FALSE, keep.tree = FALSE,
keep.class = FALSE, regex = FALSE, invert = FALSE, ...)
## Check for the existence of elements
has_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
orFALSE
when applied to elements ofl
, or a character vector of element names or regular expressions (ifregex = 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, whileFALSE
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
(ifregex = 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")
.
Examples
m <- qM(mtcars)
get_elem(list(list(list(m))), is.matrix)
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
#> Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
#> Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
#> Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
#> Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
#> Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
#> [ reached getOption("max.print") -- omitted 26 rows ]
get_elem(list(list(list(m))), is.matrix, keep.tree = TRUE)
#> [[1]]
#> [[1]][[1]]
#> [[1]][[1]][[1]]
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
#> Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
#> Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
#> Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
#> Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
#> Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
#> [ reached getOption("max.print") -- omitted 26 rows ]
#>
#>
#>
l <- list(list(2,list("a",1)),list(1,list("b",2)))
has_elem(l, is.logical)
#> [1] FALSE
has_elem(l, is.numeric)
#> [1] TRUE
get_elem(l, is.character)
#> [[1]]
#> [1] "a"
#>
#> [[2]]
#> [1] "b"
#>
get_elem(l, is.character, keep.tree = TRUE)
#> [[1]]
#> [[1]][[1]]
#> [[1]][[1]][[1]]
#> [1] "a"
#>
#>
#>
#> [[2]]
#> [[2]][[1]]
#> [[2]][[1]][[1]]
#> [1] "b"
#>
#>
#>
l <- lm(mpg ~ cyl + vs, data = mtcars)
str(reg_elem(l))
#> List of 9
#> $ coefficients : Named num [1:3] 39.625 -3.091 -0.939
#> ..- attr(*, "names")= chr [1:3] "(Intercept)" "cyl" "vs"
#> $ residuals : Named num [1:32] -0.081 -0.081 -3.523 1.258 3.8 ...
#> ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#> $ effects : Named num [1:32] -113.65 -28.6 1.54 2.39 3.75 ...
#> ..- attr(*, "names")= chr [1:32] "(Intercept)" "cyl" "vs" "" ...
#> $ rank : int 3
#> $ fitted.values: Named num [1:32] 21.1 21.1 26.3 20.1 14.9 ...
#> ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#> $ assign : int [1:3] 0 1 2
#> $ qr :List of 5
#> ..$ qr : num [1:32, 1:3] -5.657 0.177 0.177 0.177 0.177 ...
#> .. ..- attr(*, "dimnames")=List of 2
#> .. .. ..$ : chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
#> .. .. ..$ : chr [1:3] "(Intercept)" "cyl" "vs"
#> .. ..- attr(*, "assign")= int [1:3] 0 1 2
#> ..$ qraux: num [1:3] 1.18 1.02 1.13
#> ..$ pivot: int [1:3] 1 2 3
#> ..$ tol : num 1e-07
#> ..$ rank : int 3
#> $ df.residual : int 29
#> $ model :'data.frame': 32 obs. of 3 variables:
#> ..$ mpg: num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
#> ..$ cyl: num [1:32] 6 6 4 6 8 6 8 4 4 6 ...
#> ..$ vs : num [1:32] 0 0 1 1 0 1 0 1 1 1 ...
#> ..- attr(*, "terms")=Classes 'terms', 'formula' language mpg ~ cyl + vs
#> .. .. ..- attr(*, "variables")= language list(mpg, cyl, vs)
#> .. .. ..- attr(*, "factors")= int [1:3, 1:2] 0 1 0 0 0 1
#> .. .. .. ..- attr(*, "dimnames")=List of 2
#> .. .. .. .. ..$ : chr [1:3] "mpg" "cyl" "vs"
#> .. .. .. .. ..$ : chr [1:2] "cyl" "vs"
#> .. .. ..- attr(*, "term.labels")= chr [1:2] "cyl" "vs"
#> .. .. ..- attr(*, "order")= int [1:2] 1 1
#> .. .. ..- attr(*, "intercept")= int 1
#> .. .. ..- attr(*, "response")= int 1
#> .. .. ..- attr(*, ".Environment")=<environment: 0x10a7dab18>
#> .. .. ..- attr(*, "predvars")= language list(mpg, cyl, vs)
#> .. .. ..- attr(*, "dataClasses")= Named chr [1:3] "numeric" "numeric" "numeric"
#> .. .. .. ..- attr(*, "names")= chr [1:3] "mpg" "cyl" "vs"
str(irreg_elem(l))
#> List of 2
#> $ call : language lm(formula = mpg ~ cyl + vs, data = mtcars)
#> $ terms:Classes 'terms', 'formula' language mpg ~ cyl + vs
#> .. ..- attr(*, "variables")= language list(mpg, cyl, vs)
#> .. ..- attr(*, "factors")= int [1:3, 1:2] 0 1 0 0 0 1
#> .. .. ..- attr(*, "dimnames")=List of 2
#> .. .. .. ..$ : chr [1:3] "mpg" "cyl" "vs"
#> .. .. .. ..$ : chr [1:2] "cyl" "vs"
#> .. ..- attr(*, "term.labels")= chr [1:2] "cyl" "vs"
#> .. ..- attr(*, "order")= int [1:2] 1 1
#> .. ..- attr(*, "intercept")= int 1
#> .. ..- attr(*, "response")= int 1
#> .. ..- attr(*, ".Environment")=<environment: 0x10a7dab18>
#> .. ..- attr(*, "predvars")= language list(mpg, cyl, vs)
#> .. ..- attr(*, "dataClasses")= Named chr [1:3] "numeric" "numeric" "numeric"
#> .. .. ..- attr(*, "names")= chr [1:3] "mpg" "cyl" "vs"
get_elem(l, is.matrix)
#> (Intercept) cyl vs
#> Mazda RX4 -5.6568542 -35.00178567 -2.47487373
#> Mazda RX4 Wag 0.1767767 9.94359090 -2.27533496
#> Datsun 710 0.1767767 0.21715832 -1.64251357
#> Hornet 4 Drive 0.1767767 0.01602374 0.36419832
#> Hornet Sportabout 0.1767767 -0.18511084 -0.01520019
#> Valiant 0.1767767 0.01602374 0.36419832
#> Duster 360 0.1767767 -0.18511084 -0.01520019
#> Merc 240D 0.1767767 0.21715832 0.13477385
#> Merc 230 0.1767767 0.21715832 0.13477385
#> Merc 280 0.1767767 0.01602374 0.36419832
#> Merc 280C 0.1767767 0.01602374 0.36419832
#> Merc 450SE 0.1767767 -0.18511084 -0.01520019
#> Merc 450SL 0.1767767 -0.18511084 -0.01520019
#> Merc 450SLC 0.1767767 -0.18511084 -0.01520019
#> Cadillac Fleetwood 0.1767767 -0.18511084 -0.01520019
#> Lincoln Continental 0.1767767 -0.18511084 -0.01520019
#> Chrysler Imperial 0.1767767 -0.18511084 -0.01520019
#> Fiat 128 0.1767767 0.21715832 0.13477385
#> Honda Civic 0.1767767 0.21715832 0.13477385
#> Toyota Corolla 0.1767767 0.21715832 0.13477385
#> Toyota Corona 0.1767767 0.21715832 0.13477385
#> Dodge Challenger 0.1767767 -0.18511084 -0.01520019
#> AMC Javelin 0.1767767 -0.18511084 -0.01520019
#> [ reached getOption("max.print") -- omitted 9 rows ]
#> attr(,"assign")
#> [1] 0 1 2
get_elem(l, "residuals")
#> Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive
#> -0.0809747 -0.0809747 -3.5232427 1.2581068
#> Hornet Sportabout Valiant Duster 360 Merc 240D
#> 3.8003749 -2.0418932 -0.5996251 -1.9232427
#> Merc 230 Merc 280 Merc 280C Merc 450SE
#> -3.5232427 -0.9418932 -2.3418932 1.5003749
#> Merc 450SL Merc 450SLC Cadillac Fleetwood Lincoln Continental
#> 2.4003749 0.3003749 -4.4996251 -4.4996251
#> Chrysler Imperial Fiat 128 Honda Civic Toyota Corolla
#> -0.1996251 6.0767573 4.0767573 7.5767573
#> Toyota Corona Dodge Challenger AMC Javelin Camaro Z28
#> -4.8232427 0.6003749 0.3003749 -1.5996251
#> Pontiac Firebird Fiat X1-9 Porsche 914-2 Lotus Europa
#> 4.3003749 0.9767573 -1.2623243 4.0767573
#> Ford Pantera L Ferrari Dino Maserati Bora Volvo 142E
#> 0.9003749 -1.3809747 0.1003749 -4.9232427
get_elem(l, "fit", regex = TRUE)
#> Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive
#> 21.08097 21.08097 26.32324 20.14189
#> Hornet Sportabout Valiant Duster 360 Merc 240D
#> 14.89963 20.14189 14.89963 26.32324
#> Merc 230 Merc 280 Merc 280C Merc 450SE
#> 26.32324 20.14189 20.14189 14.89963
#> Merc 450SL Merc 450SLC Cadillac Fleetwood Lincoln Continental
#> 14.89963 14.89963 14.89963 14.89963
#> Chrysler Imperial Fiat 128 Honda Civic Toyota Corolla
#> 14.89963 26.32324 26.32324 26.32324
#> Toyota Corona Dodge Challenger AMC Javelin Camaro Z28
#> 26.32324 14.89963 14.89963 14.89963
#> Pontiac Firebird Fiat X1-9 Porsche 914-2 Lotus Europa
#> 14.89963 26.32324 27.26232 26.32324
#> Ford Pantera L Ferrari Dino Maserati Bora Volvo 142E
#> 14.89963 21.08097 14.89963 26.32324
has_elem(l, "tol")
#> [1] TRUE
get_elem(l, "tol")
#> [1] 1e-07