4

I often find myself creating a list from several variables, then renaming the list to use those variable names as the name of the list so I can access them with $ notation or use bind_rows with the .id argument:

a <- 1:10
b <- 11:20
mylist <- list(a, b)
names(mylist) <- c("a", "b")
mylist$a
[1]  1  2  3  4  5  6  7  8  9 10

I can't figure out how to skip this second step and tell R to just use the variable names as the names within the list:

list(a, b)$a
NULL

This seems like it should be doable because it's the default behavior for data.frame:

data.frame(a, b)$a
[1]  1  2  3  4  5  6  7  8  9 10

but using this method only works if the variables all have exactly the same length. It might seem like a simple thing to just use something like

mylist <- list(a=a, b=b)

but this feels redundant, becomes painful with long variable names, and I've often introduced bugs with typos that I don't notice until later.

Is there a way to construct a list in R from some variables that automatically names the list with the variable names?

2 Answers 2

7

We may use dplyr::lst

library(dplyr)
lst(a, b)$a
 [1]  1  2  3  4  5  6  7  8  9 10

Or in a chain

lst(a, b)  %>% 
 pluck("a")
 [1]  1  2  3  4  5  6  7  8  9 10
Sign up to request clarification or add additional context in comments.

Comments

4

Please, just use base R's mget for that task ...

a <- 1:10
b <- 11:20
mget(c("a", "b"))
$a
 [1]  1  2  3  4  5  6  7  8  9 10

$b
 [1] 11 12 13 14 15 16 17 18 19 20

mget is faster than tibble::lst (also available as dplyr::lst):

microbenchmark::microbenchmark(mget(c("a", "b")), tibble::lst(a, b), times = 10000L)
Unit: nanoseconds
              expr   min    lq       mean median    uq     max neval
 mget(c("a", "b"))   492   615   726.4995    697   738   32390 10000
 tibble::lst(a, b) 36039 37474 42023.1345  37966 38786 1408309 10000

It is also better for programming. Suppose that you want a list containing each variable in your environment whose name begins with zzz. Then you could do mget(grep("^zzz", ls(), value = TRUE)). It is not so clear how you would accomplish that with tibble::lst.

tibble::lst is primarily useful when you want to evaluate nontrivial expressions (i.e., calls rather than symbols) with recursive access to the values of earlier arguments:

tibble::lst(x = a + b, y = x * exp(-b), z = y + 1, z - 1)
$x
 [1] 12 14 16 18 20 22 24 26 28 30

$y
 [1] 2.004204e-04 8.601897e-05 3.616527e-05 1.496752e-05 6.118046e-06
 [6] 2.475774e-06 9.935851e-07 3.959795e-07 1.568783e-07 6.183461e-08

$z
 [1] 1.000200 1.000086 1.000036 1.000015 1.000006 1.000002 1.000001 1.000000
 [9] 1.000000 1.000000

$`z - 1`
 [1] 2.004204e-04 8.601897e-05 3.616527e-05 1.496752e-05 6.118046e-06
 [6] 2.475774e-06 9.935851e-07 3.959795e-07 1.568783e-07 6.183461e-08

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.