"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
我有:
- 包含文件的目录(假设两个:A 和 B);
- 存储目录的两个字符对象(
dir_A
, dir_B
);
- 一个函数,它将目录作为参数,returns 是在那里找到的文件的名称列表(对我来说这是一种不同于
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))
returns "dir_A"(因此,sub()
函数如上所示将 return "A"),在我看来,在 for 循环中 substitute(i)
使 i
不再是目录之一,而只是 i
.
因此 deparse(substitute(i))
returns "i"
并且上面的 for 循环的输出只有一个对象 files_i
,它包含列表迭代最后一个目录中的文件,因为这是最后一个在 files_i
.
上被覆盖的文件
如何让 for 循环读取当时 i
代表的对象的名称(或我的部分名称,但它是相同的)?
这里有两个问题,我觉得:
- 如何在
list
中引用名称(或索引)和每个元素的值;和
- 如何将数据从命名的
list
传输到全局(或任何)环境中。
1。引用 name/index 数据
一旦使用 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
来获取索引非常容易,但我更愿意避免 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
在您的问题中,您这样做是为了将列表中的变量分配给另一个环境。关于 努力的一些想法:
如果都相似(相同结构,不同数据),则不要。将它们保存在 list
中并使用 lapply
或类似的方法对它们进行整体处理。 (How do I make a list of data frames?)
如果您确实需要将它们从列表移动到全局环境,那么 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
我有:
- 包含文件的目录(假设两个:A 和 B);
- 存储目录的两个字符对象(
dir_A
,dir_B
); - 一个函数,它将目录作为参数,returns 是在那里找到的文件的名称列表(对我来说这是一种不同于
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))
returns "dir_A"(因此,sub()
函数如上所示将 return "A"),在我看来,在 for 循环中 substitute(i)
使 i
不再是目录之一,而只是 i
.
因此 deparse(substitute(i))
returns "i"
并且上面的 for 循环的输出只有一个对象 files_i
,它包含列表迭代最后一个目录中的文件,因为这是最后一个在 files_i
.
如何让 for 循环读取当时 i
代表的对象的名称(或我的部分名称,但它是相同的)?
这里有两个问题,我觉得:
- 如何在
list
中引用名称(或索引)和每个元素的值;和 - 如何将数据从命名的
list
传输到全局(或任何)环境中。
1。引用 name/index 数据
一旦使用 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
来获取索引非常容易,但我更愿意避免 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
在您的问题中,您这样做是为了将列表中的变量分配给另一个环境。关于 努力的一些想法:
如果都相似(相同结构,不同数据),则不要。将它们保存在
list
中并使用lapply
或类似的方法对它们进行整体处理。 (How do I make a list of data frames?)如果您确实需要将它们从列表移动到全局环境,那么
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