sarath gk
sarath gk

Reputation: 49

Creating list in R, when some of the list elements are not available

I want to create a list based on some of the elements, even if the elements are not available.

> group_vars <- list(hhrace,hhethn,hhsize,hhinc,hhage,hhcnty,hhkids,hhgeo)

here hhrace and hhcnty do not exist, but I want to create a list without those elements.

> group_vars <- list(hhrace,hhethn,hhsize,hhinc,hhage,hhcnty,hhkids,hhgeo)
  Error: object 'hhrace' not found

Desired Output-

> group_vars
  hhethn,hhsize,hhinc,hhage,hhkids,hhgeo

without the hhrace and the hhcnty.

Upvotes: 4

Views: 216

Answers (3)

Rushabh Patel
Rushabh Patel

Reputation: 2764

You can do something like this-

INPUT-

> objects <- c("hhrace","hhethn","hhsize","hhinc","hhage","hhcnty","hhkids","hhgeo")
> hhsize=list(a=2)
> hhinc=list(a=5)
> hhethn=list(a=50)

> sapply(objects,function(x) if(exists(x)) TRUE else  FALSE)

OUTPUT-

hhrace hhethn hhsize  hhinc  hhage hhcnty hhkids  hhgeo 
 FALSE   TRUE   TRUE   TRUE  FALSE  FALSE  FALSE  FALSE 

Note- To get available lists in your env you can use below code-

To just get list names which are available in env you can use-

> names(which(sapply(objects,function(x) if(exists(x)) TRUE else  FALSE)))
[1] "hhethn" "hhsize" "hhinc" 

To get complete list elements you can use below code

> mget(names(which(sapply(objects,function(x) if(exists(x)) TRUE else  FALSE))))

$hhethn
$hhethn$a
[1] 50


$hhsize
$hhsize$a
[1] 2


$hhinc
$hhinc$a
[1] 5

Upvotes: 0

dave-edison
dave-edison

Reputation: 3736

You can store them in a list of expressions with rlang::exprs and only keep the ones which exist:

library(purrr)

# define variables in global environment
hhethn <- hhsize <- hhinc <- hhage <- hhkids <- hhgeo <- TRUE

group_vars <- rlang::exprs(hhrace, hhethn, hhsize, hhinc, hhage, hhcnty, hhkids, hhgeo) %>% 
  keep(~exists(as.character(.x))) %>% 
  set_names(as.character(.)) %>% 
  map(eval)

group_vars
#$hhethn
#[1] TRUE
#
#$hhsize
#[1] TRUE
#
#$hhinc
#[1] TRUE
#
#$hhage
#[1] TRUE
#
#$hhkids
#[1] TRUE
#
#$hhgeo
#[1] TRUE

For a more general case you can create a function:

safe_list <- function(...){
  rlang::enexprs(...) %>% 
    keep(~exists(as.character(.x))) %>%
    set_names(as.character(.)) %>% 
    map(eval)
}

group_vars <- safe_list(hhrace, hhethn, hhsize, hhinc, hhage, hhcnty, hhkids, hhgeo)

Upvotes: 4

coffeinjunky
coffeinjunky

Reputation: 11514

I just want to pick up a solution suggested in the comments, which I believe is more useful than appreciated.

To set the stage, let's create the objects as DiceboyT has done:

hhethn <- hhsize <- hhinc <- hhage <- hhkids <- hhgeo <- TRUE

I am also creating a vector with the names of the existing objects:

objects <- c("hhrace","hhethn","hhsize","hhinc","hhage","hhcnty","hhkids","hhgeo")

Now, I may be wrong, but I have a hunch that all you need is the vector of objects that actually exist. The following would help with that:

objects[objects %in% ls()]
[1] "hhethn" "hhsize" "hhinc"  "hhage"  "hhkids" "hhgeo" 

However, if you truly want to list, the following would help as well, setting all missing elements to FALSE:

mget(objects, ifnotfound = FALSE)
$hhrace
[1] FALSE
$hhethn
[1] TRUE
$hhsize
[1] TRUE
$hhinc
[1] TRUE
$hhage
[1] TRUE
$hhcnty
[1] FALSE
$hhkids
[1] TRUE
$hhgeo
[1] TRUE

Now, to get a list of these except for the missing ones, we could also do the following:

tmpfun <- function(lst, nme) {
  tryCatch(
    lst[[nme]] <- get(nme)
    , error = function(e) {return(lst)}
  )
  return(lst)
}

Reduce(tmpfun, objects, init = list())
$hhethn
[1] TRUE
$hhsize
[1] TRUE
$hhinc
[1] TRUE
$hhage
[1] TRUE
$hhkids
[1] TRUE
$hhgeo
[1] TRUE

which gives you the above results except for the cases where the object does not exist.

Upvotes: 2

Related Questions