Home > Enterprise >  Looping through environment objects with a special pattern
Looping through environment objects with a special pattern

Time:05-14

I have a multiple lists in my environment(all start with "CDS_"). Each list is conducted of multiple sub lists.I want to call the lists one by one to apply a function for each of these objects. This is what I am trying:

lists<-grep("CDS_",names(.GlobalEnv),value=TRUE)  #Lists all objectrs staring with "CDS_"

for (i in seq_along(lists)){
  data<-do.call("list",mget(lists[i]))  #this line blends all sub lists into one list
  assign(paste("Df_", lists[i], sep = "_"), my_function(data)      # my_function requires a list with multiple sub lists
  }
 

but the issue is the do.call("list",mget(lists[i])) blends all sub lists into one. For example if there is a list with one sub list it returns the list but all sub lists go into one!

Any solutions how to make this work?

here is a sample to test:

#Defining my_function pulling out the sub list which contains "sample1"

my_function<-function(.data){           
  # pull out the undergraduate data
  grep("sample1", .data, value = TRUE) 
  
}

# 1st list
list_1 <- list(1:54,                             
               c("This","is","sample1","for","list1"),
               c("This","is","sample2","for","list1"),
               "Hi")

# 2nd list
list_2 <- list(51:120,                             
               c("This","is","sample1","for","list1"),
               c("This","is","sample2","for","list1"),
               "Bus")

# 3rd list
list_3 <- list(90:120, 
               letters[16:11],
               2025)





lists<-grep("list_",names(.GlobalEnv),value=TRUE)
for (i in seq_along(lists)){
  data<-do.call("list",mget(lists[i]))
  assign(paste("sample1_", lists[i], sep = ""), my_function(data))
} 

CodePudding user response:

As mentioned by @MrFlick, R has a ton of list functionality. It is usually the case that you are better off storing your lists in a list than trying to directly edit them in the environment. Here is one possible solution using base R:

l <- mget(ls(pattern = "^list_\\d$")) # store lists in a list

lapply(l, \(x) lapply(x, my_function))
$list_1
$list_1[[1]]
character(0)

$list_1[[2]]
[1] "sample1"

$list_1[[3]]
character(0)

$list_1[[4]]
character(0)


$list_2
$list_2[[1]]
character(0)

$list_2[[2]]
[1] "sample1"

$list_2[[3]]
character(0)

$list_2[[4]]
character(0)


$list_3
$list_3[[1]]
character(0)

$list_3[[2]]
character(0)

$list_3[[3]]
character(0)

Update

Sticking with base R to remove non-matches you could do:

lapply(l, \(x) Filter(length, lapply(x, my_function)))
$list_1
$list_1[[1]]
[1] "sample1"


$list_2
$list_2[[1]]
[1] "sample1"


$list_3
list()

A purrr solution would be:

library(purrr)

map(map_depth(l, 2, my_function), compact)

CodePudding user response:

When you have lists of lists, and option is rapply, the recursive version of lapply.

my_function<-function(.data){           
  # pull out the undergraduate data
  grep("sample1", .data, value = TRUE) 
}

lists <- mget(ls(pattern = "^list_"))

rapply(lists, my_function, how = "list")
#> $list_1
#> $list_1[[1]]
#> character(0)
#> 
#> $list_1[[2]]
#> [1] "sample1"
#> 
#> $list_1[[3]]
#> character(0)
#> 
#> $list_1[[4]]
#> character(0)
#> 
#> 
#> $list_2
#> $list_2[[1]]
#> character(0)
#> 
#> $list_2[[2]]
#> [1] "sample1"
#> 
#> $list_2[[3]]
#> character(0)
#> 
#> $list_2[[4]]
#> character(0)
#> 
#> 
#> $list_3
#> $list_3[[1]]
#> character(0)
#> 
#> $list_3[[2]]
#> character(0)
#> 
#> $list_3[[3]]
#> character(0)

Created on 2022-05-13 by the reprex package (v2.0.1)


Edit

To answer to the OP's comment to another answer, to keep only the matches, save the rapply result and a lapply loop calling lengths, the list version of vector length is used to extract the matches.

r <- rapply(lists, my_function, how = "list")
lapply(r, \(x) x[lengths(x) > 0])
#> $list_1
#> $list_1[[1]]
#> [1] "sample1"
#> 
#> 
#> $list_2
#> $list_2[[1]]
#> [1] "sample1"
#> 
#> 
#> $list_3
#> list()

Created on 2022-05-13 by the reprex package (v2.0.1)

  •  Tags:  
  • r
  • Related