使用 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 循环的主要内容,如果未能解决你的问题,请参考以下文章

R:试图理解逻辑以用lapply()替换循环

是否可以在 grepl() 中使用 AND 运算符?

使用 grepl 在 R 中提取子字符串

使用 grepl 在 R 中获取匹配的字符串

结合 grepl 过滤 dplyr 中的观察结果

grepl()中如何使用运算符OR