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
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 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, ...)
a list.
a list of the same length as the extracted subset of l
.
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.
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.
logical. Should the list search be recursive (i.e. go though all the elements), or just at the top-level?
logical. TRUE
treats data frames like (sub-)lists; FALSE
like atomic elements.
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.
logical. For objects: should the class be retained?
logical. Should regular expression search be used on the list names, or only exact matches?
logical. Invert search i.e. exclude matched elements from the list?
further arguments to grep
(if regex = TRUE
).
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")
.
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: 0x12c2ef4a8>
#> .. .. ..- 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: 0x12c2ef4a8>
#> .. ..- 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