尝试学习 R 中的诀窍,并且已经在努力寻找 SAS 宏的替代品。
我试图多次运行一段代码,但我遇到了困难,所以来这里寻求帮助。
首先,我正在处理这个示例文件,其中一个变量提供了我之前在另一个文件 (qtde_registros) 中分析的行数,后面跟着三个变量提供了具有不同值的行数错误类型。
file <- readRDS(file="file.Rda")
file
qtde_registros error1 error2 error3
1 1175 0 0 0
之后,我创建了一个包含错误的列表和另一个包含每个错误的描述的列表。 然后,使用这些列表和最初提到的文件,我希望创建几个文件(每个错误一个),稍后将这些文件绑定(bind)到最后一个文件中以形成最终报告。
正如我所说,我正在努力解决这个问题,因此我制作了一个示例代码来说明如何形成第一个文件:
error_list <- list("Error1","Error2","Error3",)
description_list <- list("Code not found",
"Invalid date.",
"Negative value.")
error1 <- file
error1$file_name <- "Clients"
error1$error <- error_list[1]
error1$qtde <- error1$error1
error1$desc <- description_list[1]
error1 <- select(error1, file_name, error, qtde, desc)
error1
file_name error qtde desc
1 Clients Error1 0 Code not found
这引出了我的问题:如何使上面的代码运行多次,列表中的每个错误运行一次?
我知道整个心态可能不是最好的,因为根据所使用的语言,做某些事情的方法会有所不同,但我必须利用我目前拥有的知识。
我正在考虑使用 apply 系列函数,但我没有成功。
提前感谢您的帮助,并对打字或语法中的任何错误表示歉意(英语不是我的母语)。
编辑:忘了说我不打算通过 For 或 While 循环来完成。
最佳答案
在 R(以及许多其他语言)中,您将使用 for-loop
的形式。 。在 R 中,*apply
系列中有几个具有特定结果的 for 循环包装器。这是 *apply
系列及其输入/输出的简短(不完整)列表:
lapply
-> 列出输出sapply
-> 列表或原子(整数向量、数值向量等)mapply
-> 与sapply
类似,但可以接受超过 1 个输入来遍历(例如,如果您同时有 2 个事物需要循环)tapply
-> 循环INDEX
定义的组apply
-> 循环数组(行或列)返回矩阵/向量
等等。
我猜您的示例不完整,但我将展示 3 个示例来帮助您入门。一种使用 for 循环
,一种使用 lapply
,一种使用 mapply
。
for循环
for 循环是经典方法(在大多数编程语言中都有)。它的工作原理是使用 for(---)
,其中 ---
被替换为要迭代的内容。这可以是 error_list
也可以是数值向量 seq(1, n)
或 1:n
。这里你有不止一个东西需要迭代,所以数字向量是有意义的(我们用它来子集数据)
errors <- list() # <== Somewhere to put our results
for(i in 1:length(error_list)){
error_i <- list(file = file,
file_name = "Clients",
error = error_list[[i]], # Use i to subset error_list
qtde = error_list[[i]], # Maybe this should be something else in your case
desc = description_list[[i]]
)
# Put into our errors list. Create "error1" using paste and our index
errors[[paste0('error', i)]] <- error_i
}
最后,所有结果都将位于 errors
列表中,并使用 errors[1]
或 errors["errors1"]< 进行提取
(将数字更改为您的错误)。然后可以使用 do.call(rbind, error) 组合,然后使用 write.table (或 write.csv 或类似的)保存.
lapply
对于 *apply
系列,*apply
负责循环。但我们必须提供一个在每次迭代中执行的函数(SAS 术语中的宏)。因此,我们将循环的内容包装在上面的函数中。
macro <- function(i){
list(file = file,
file_name = "Clients",
error = error_list[[i]], # Use i to subset error_list
qtde = error_list[[i]], # Maybe this should be something else in your case?
desc = description_list[[i]]
)
}
errors <- lapply(1:length(error_list), macro)
#set names afterwards
names(errors) <- paste0("error", 1:length(error_list))
我们再次准备好要提取的数据并保存等。这相当于:
errors <- list()
for(i in 1:length(error_list))
errors[[i]] <- macro(i)
names(errors) <- paste0("error", 1:length(error_list))
映射
现在,在您的情况下,您有不止一件事需要迭代。另一种方法是使用 mapply
并将它们作为参数添加到您的函数中。这样我们就可以从函数中删除 error_list[[i]]
和 description_list[[i]]
并将它们添加为参数
macro_mapply <- function(error, description){
list(file = file,
file_name = "Clients",
error = error, # No need to use I here anymore
qtde = error, # Maybe this should be something else in your case?
desc = description
)
}
errors <- mapply(macro_mapply,
# parameters to iterate over comes after function
error = error_list,
description = description_list,
# Avoid simplification (if we want a list returned)
SIMPLIFY = FALSE)
names(errors) <- paste0("error", 1:length(error_list))
请注意,如果可能,“mapply”将尝试返回向量,因此我设置 SIMPLIFY = FALSE
来避免这种情况。
注意事项:
在上面的 3 个示例中,我没有考虑您是否读取多个文件
,或任何其他参数发生变化。因此,如果您必须在每次迭代中读取文件,那么使用前 2 个示例并将 readRDS
添加到具有适当文件命名的循环或函数中是有意义的。我也使用了您的数据,但我猜测 qtde
和 error
在您的具体情况下应该有所不同,但这从您的示例中并不清楚。
我希望这能帮助您入门。
一旦您掌握了第一个循环的窍门,并且对 *apply
的工作原理有所了解,我建议您查看 tidyverse
它提供了许多人认为更“用户友好”且直观的数据转换界面。
我希望这将帮助您开始解决您的问题。
关于多次运行一段代码,更改 R 中的某些参数(如 SAS 中的宏),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66583564/