以特殊模式循环遍历环境对象



我的环境中有多个列表(都以"CDS_"开头)。每个列表由多个子列表组成。我想一个接一个地调用列表,为每个对象应用一个函数。这就是我正在尝试的:

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
}

,但问题是do.call("list",mget(lists[i]))将所有子列表合并为一个。例如,如果有一个包含一个子列表的列表,它将返回该列表,但所有子列表都包含在一个列表中!

有任何解决方案如何使其工作?

这里有一个要测试的示例:

#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))
} 

正如@MrFlick所提到的,R有大量的列表功能。通常情况下,最好将列表存储在列表中,而不是在环境中直接编辑它们。下面是使用基数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)

更新

坚持以R为基础来删除不匹配,你可以这样做:

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()

purrr的解是:

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

当您有列表的列表,并且选项是rapply,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)

在2022-05-13由reprex包(v2.0.1)创建


编辑

为了回答OP对另一个答案的评论,为了只保留匹配,保存rapply结果和调用lengthslapply循环,使用向量长度的列表版本提取匹配。

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()

在2022-05-13由reprex包(v2.0.1)创建

最新更新