我有:
- 目录(假设两个:A和B(,其中包含文件
- 存储目录的两个字符对象(
dir_A
、dir_B
( - 一个函数,它将目录作为参数,并返回在那里找到的文件的名称列表(对我来说,这是一种不同于
list.files()
的方便方式(
directories <- c(dir_A, dir_B)
read_names <- function(x) {foo}
使用for循环,我想创建对象,每个对象都包含read_names()
给出的不同目录的文件列表。从本质上讲,我想使用for循环来做等效的事情:
files_A <- read_names(dir_A)
files_B <- read_names(dir_B)
我写的循环如下:
for (i in directories) {
assign(paste("files_", sub('.*\_', '', deparse(substitute(i))), sep = ""), read_names(i))
}
然而,尽管在for循环之外,deparse(substitute(dir_A))
返回"dir_A"(因此,如上所述编写的sub()
函数将返回"A"(,但在我看来,在for循环中,substitute(i)
使i
不再是目录之一,而只是i
。
因此,deparse(substitute(i))
返回"i"
,上面for循环的输出只有一个名为files_i
的对象,它包含迭代的最后一个目录中的文件列表,因为这是files_i
上最后一个被覆盖的文件。
我如何让for循环读取i
在那一刻所代表的对象的名称(或者在我的情况下是名称的一部分,但它是相同的(?
我认为这里有两个问题:
- 如何引用
list
中每个元素的名称(或索引(和值;以及 - 如何将数据从命名的
list
传输到全局(或任何(环境中
1.带数据的引用名称/索引
使用for (i in directories)
进行索引后,directories
中i
的完整上下文(索引、名称(将丢失。一些替代方案:
for (ix in seq_along(directories)) {
directories[[ix]] # the *value*
names(directories)[ix] # the *name*
ix # the *index*
# ...
}
for (nm in names(directories)) {
directories[[nm]] # the *value*
nm # the *name*
match(nm, names(directories)) # the *index*
# ...
}
如果你愿意接受类似Map
的函数(一种处理类似事物列表的更惯用的方法(,那么
out <- Map(function(x, nm) {
x # the *value*
nm # the *name*
# ...
}, directories, names(directories))
out <- purrr::imap(directories, function(x, nm) {
x # the *value*
nm # the *name*
# ...
})
# there are other ways to identify the function in `purrr::` functions
注意:虽然在最后两个中使用match
来获取索引非常容易,但这是一个小的范围违反,我更愿意在合理的情况下避免。它有效,我只是更喜欢其他方法。如果您想要值、名称、和索引,则
out <- Map(function(x, nm, ix) {
x # the *value*
nm # the *name*
ix # the *index*
# ...
}, directories, names(directories), seq_along(directories))
2.将列表传输到env
在您的问题中,您这样做是为了将列表中的变量分配到另一个环境中。关于努力的一些想法:
如果它们都相似(相同的结构,不同的数据(,则不要。将它们保存在
list
中,并使用lapply
或类似工具对它们进行整体处理。(如何列出数据帧?(如果您确实需要将它们从列表移动到全局环境,那么
list2env
在这里可能很有用。# create my fake data directories <- list(a=1, b=2) # this is your renaming step, rename before storing in the global env # ... not required unless you have no names or want/need different names names(directories) <- paste0("files_", names(directories)) # here the bulk of the work; you can safely ignore the return value list2env(directories, envir = .GlobalEnv) # <environment: R_GlobalEnv> ls() # [1] "directories" "files_a" "files_b" files_a # [1] 1