使用 grepl 循环
Posted
技术标签:
【中文标题】使用 grepl 循环【英文标题】:For loop using grepl 【发布时间】:2022-01-20 16:14:49 【问题描述】:示例数据
我正在编写一个脚本,旨在将输入文件复制到多个位置。以下是实现此目的的功能代码示例:
##### File 1 #####
output_paths_1 <- list(c(paste0(path_1, "file_1", ".xlsx"),
paste0(path_2, "file_1", ".xlsx"),
paste0(path_3, "file_1", " ", gsub("-", "", Sys.Date()), ".xlsx")))
lapply(output_paths_1, function (x) file.copy(paste0(input_path, "input_1.xlsx"), x, overwrite = T))
##### File 2 #####
output_paths_2 <- list(c(paste0(path_1, "file_2", ".xlsx"),
paste0(path_2, "file_2", ".xlsx"),
paste0(path_3, "file_2", " ", gsub("-", "", Sys.Date()), ".xlsx")))
lapply(output_paths_2, function (x) file.copy(paste0(input_path, "input_2.xlsx"), x, overwrite = T))
##### File 3 #####
output_paths_3 <- list(c(paste0(path_1, "file_3", ".xlsx"),
paste0(path_2, "file_3", ".xlsx"),
paste0(path_3, "file_3", " ", gsub("-", "", Sys.Date()), ".xlsx")))
lapply(output_paths_3, function (x) file.copy(paste0(input_path, "input_3.xlsx"), x, overwrite = T))
代表
但我怀疑还有更有效的方法。在我最近的尝试中,它不起作用,我使用了嵌套的“for”循环。我创建包含每个输入和文件名的数据框。然后(理论上),对于inputs
中的每个i
,我为files
中的每个i
编写一个output paths
数据框。我使用grepl
一次只为一个文件过滤这个数据框。见以下代码:
files <- data.frame(data = c("file_1", "file_2", "file_3"))
inputs <- data.frame(data = c("input_1.xlsx", "input_2.xlsx", "input_3.xlsx"))
for (i in seq_along(inputs))
for (i in seq_along(files))
output_paths <- data.frame(data = c(paste0(path_1, files[[i]], ".xlsx"),
paste0(path_2, files[[i]], ".xlsx"),
paste0(path_3, files[[i]], " ", gsub("-", "", Sys.Date()), ".xlsx"))) %>%
filter(grepl(files[[i]], `data`))
lapply(output_paths, function (x) file.copy(paste0(input_path, inputs[[i]]), x, overwrite = T))
我希望这会将第一个文件复制到三个位置,然后将下一个文件复制到这些相同的位置,等等。相反,会出现以下警告,并且只有第一个文件被复制到所需的位置:
Warning message:
In grepl(files[[i]], data) :
argument 'pattern' has length > 1 and only the first element will be used
运行包含grepl
函数的代码没有什么都不做 - 没有文件被复制到所需的位置。
问题:
-
如何调整上面的代码来迭代所有元素,而不是只迭代第一个元素?
还有更优雅的方法吗? (只是寻找指针,不一定代表)
【问题讨论】:
在嵌套的 for 循环中,您将i
分配为 seq_along(inputs)
,然后将相同的 i
覆盖为 seq_along(files)
。您需要为每个循环分配不同的向量。例如,将j
分配为seq_along(files)
并将所有files[[i]]
更改为files[[j]]
。这可能会解决您的问题(我还没有尝试过)。
【参考方案1】:
我不明白你想用你的“Reprex”方法来完成什么。但是,如果您想通过编写更少的代码来完成您的第一个但代码所做的事情,那么您可以执行类似的操作
files = c("file1", "file2", "file3") # file names
opaths = c("path1", "path2", "path3") # output paths
df = expand.grid(file = files, path = opaths, stringsAsFactors = F)
df$from = file.path(input_path, df$file)
df$to = file.path(df$path, df$file)
file.copy(from = df$from, to = df$to)
如果您想要 path3 的文件名中的时间戳,则可以执行类似的操作
df$to[df$path == "path3"] <- file.path(df$path[df$path == "path3"],
paste0(format(Sys.Date(), "%Y%m%d_"), df$file[df$path == "path3"])
)
【讨论】:
这个选项的一个问题是,一旦文件被移动,我必须重命名它们。所以在这个例子中,我需要在数据框中包含第三个向量,可能是source = c("name1", "name2", name3")
,并使用结果列而不是df$file
来写入输入路径。以上是关于使用 grepl 循环的主要内容,如果未能解决你的问题,请参考以下文章