1

我有:

  • 包含文件的目录(比如说两个: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代表的对象的名称(或在我的情况下是名称的一部分,但它是相同的)?

4

1 回答 1

0

这里有两个问题,我认为:

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

1. 引用名称/索引与数据

使用 索引后,其中的for (i in directories)完整上下文(索引、名称)将丢失。一些替代方案:idirectories

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-like 函数(一种处理类似事物列表的更惯用的方式),那么

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

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

  1. 如果它们都相似(相同的结构,不同的数据),那么不要。将它们保存在 a 中list,然后使用lapply或类似方法对它们进行处理。(如何制作数据框列表?

  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
    
于 2019-11-18T15:40:16.470 回答