以更短的方式在 R 的 for 循环中创建和使用不同的表
Create and use different tables in for-loops in R in a shorter way
我正在寻找一个简短的解决方案来在 for 循环中创建和使用不同的表,其中循环变量是名称的一部分。
我找到了以下解决方案:
如果我想在循环中创建表,我可以将赋值和粘贴一起使用。例如:
for (f in files){
assign(paste0("A_",f), readWorksheetFromFile(paste0(f,".xlsx")))}
如果我想使用这些表,我可以按以下方式使用 eval、parse 和 paste0:
for(f in files){
x <- eval(parse(text=paste0("A_",f)))}
问题是我不得不经常使用这些结构,而且代码越来越长。有没有人有更短的解决方案来在 R 中执行此操作?
例如在 SAS 中,我可以使用类似的东西(我记得)
x = A_&f;
而不是
x <- eval(parse(text=paste0("A_",f)))
编辑
根据以下答案我找到了这个解决方案:
在循环创建对象的过程中我可能会用到函数
`%c%` = function(a, b) paste0(a, b)
对于两个或多个字符串,采用以下方式:
"A_" %c% f
"A_" %c% f %c% r
如果我想在循环中使用这个对象,我可以使用函数:
`%u%` = function(a, b) eval(parse(text=paste0(a,b)))
对于两个或多个字符串,采用以下方式:
"A_" %u% f
"A_" %c% f %u% r
请注意,我只在最后一步使用了 %u%。
您可以尝试使用列表:
l = vector("list", length(files))
names(l) = paste0("A_", files)
for(i in seq_along(files))
l[[i]] = readWorksheetFromFile(paste0(files[i],".xlsx")))
如果您需要它们是单独的变量,您可以创建自己的环境并将它们存储在那里:
myenv = new.env()
lapply(seq_along(l), function(i) assign(names(l)[i], l[[i]], pos = myenv))
并使用 get
检索变量:
vars = ls(pos = myenv)
get(vars[1], pos = myenv)
编辑
所以你真的只是在寻找像 _&
:
这样的运算符
`%&%` = function(a, b) get(paste0(a, "_", b))
"A" %&% f
A = "A"
A %&% f
当我必须批量读取许多文件时,我通常会这样做:
l <- lapply(paste0(files,".xlsx"), readWorksheetFromFile)
names(l) <- paste0("A_", files)
不需要 for
循环。
l
是一个包含名为 data.frame
的列表。使用str(l)
展示结构。
可以通过 3 种不同的方式访问单个 data.frame
或 table:
l[[1]]
l$A_File1
l[["A_File1"]]
虚拟数据
为了使其成为可重现的示例,我创建了如下虚拟数据:
set.seed(1234)
readWorksheetFromFile <- function(f) {
n <- sample.int(5, 1)
data.frame(a = sample.int(9, n), b = sample(LETTERS, n),
stringsAsFactors = FALSE)
}
files <- paste0("File", 1:5)
我正在寻找一个简短的解决方案来在 for 循环中创建和使用不同的表,其中循环变量是名称的一部分。
我找到了以下解决方案:
如果我想在循环中创建表,我可以将赋值和粘贴一起使用。例如:
for (f in files){
assign(paste0("A_",f), readWorksheetFromFile(paste0(f,".xlsx")))}
如果我想使用这些表,我可以按以下方式使用 eval、parse 和 paste0:
for(f in files){
x <- eval(parse(text=paste0("A_",f)))}
问题是我不得不经常使用这些结构,而且代码越来越长。有没有人有更短的解决方案来在 R 中执行此操作?
例如在 SAS 中,我可以使用类似的东西(我记得)
x = A_&f;
而不是
x <- eval(parse(text=paste0("A_",f)))
编辑
根据以下答案我找到了这个解决方案:
在循环创建对象的过程中我可能会用到函数
`%c%` = function(a, b) paste0(a, b)
对于两个或多个字符串,采用以下方式:
"A_" %c% f
"A_" %c% f %c% r
如果我想在循环中使用这个对象,我可以使用函数:
`%u%` = function(a, b) eval(parse(text=paste0(a,b)))
对于两个或多个字符串,采用以下方式:
"A_" %u% f
"A_" %c% f %u% r
请注意,我只在最后一步使用了 %u%。
您可以尝试使用列表:
l = vector("list", length(files))
names(l) = paste0("A_", files)
for(i in seq_along(files))
l[[i]] = readWorksheetFromFile(paste0(files[i],".xlsx")))
如果您需要它们是单独的变量,您可以创建自己的环境并将它们存储在那里:
myenv = new.env()
lapply(seq_along(l), function(i) assign(names(l)[i], l[[i]], pos = myenv))
并使用 get
检索变量:
vars = ls(pos = myenv)
get(vars[1], pos = myenv)
编辑
所以你真的只是在寻找像 _&
:
`%&%` = function(a, b) get(paste0(a, "_", b))
"A" %&% f
A = "A"
A %&% f
当我必须批量读取许多文件时,我通常会这样做:
l <- lapply(paste0(files,".xlsx"), readWorksheetFromFile)
names(l) <- paste0("A_", files)
不需要 for
循环。
l
是一个包含名为 data.frame
的列表。使用str(l)
展示结构。
可以通过 3 种不同的方式访问单个 data.frame
或 table:
l[[1]]
l$A_File1
l[["A_File1"]]
虚拟数据
为了使其成为可重现的示例,我创建了如下虚拟数据:
set.seed(1234)
readWorksheetFromFile <- function(f) {
n <- sample.int(5, 1)
data.frame(a = sample.int(9, n), b = sample(LETTERS, n),
stringsAsFactors = FALSE)
}
files <- paste0("File", 1:5)