"i" 在 for 循环中遍历 R 中的对象列表时表示的对象的访问名称

Access name of the object that "i" represents when it iterates in a for-loop through a list of objects in R

我有:

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)) returns "dir_A"(因此,sub() 函数如上所示将 return "A"),在我看来,在 for 循环中 substitute(i) 使 i 不再是目录之一,而只是 i.

因此 deparse(substitute(i)) returns "i" 并且上面的 for 循环的输出只有一个对象 files_i,它包含列表迭代最后一个目录中的文件,因为这是最后一个在 files_i.

上被覆盖的文件

如何让 for 循环读取当时 i 代表的对象的名称(或我的部分名称,但它是相同的)?

这里有两个问题,我觉得:

  1. 如何在 list 中引用名称(或索引)和每个元素的值;和
  2. 如何将数据从命名的 list 传输到全局(或任何)环境中。

1。引用 name/index 数据

一旦使用 for (i in directories) 建立索引,directoriesi 的完整上下文(索引、名称)将丢失。一些备选方案:

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 来获取索引非常容易,但我更愿意避免 scope-breach合理的时候。它有效,我只是更喜欢替代方法。如果你想要值,名称,索引,那么

out <- Map(function(x, nm, ix) {
  x                              # the *value*
  nm                             # the *name*
  ix                             # the *index*
   # ...
}, directories, names(directories), seq_along(directories))

2。将列表传输到 env

在您的问题中,您这样做是为了将列表中的变量分配给另一个环境。关于 努力的一些想法:

  1. 如果都相似(相同结构,不同数据),则不要。将它们保存在 list 中并使用 lapply 或类似的方法对它们进行整体处理。 (How do I make a list of data frames?)

  2. 如果您确实需要将它们从列表移动到全局环境,那么 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