【问题标题】:For loop using grepl使用 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 函数的代码没有什么都不做 - 没有文件被复制到所需的位置。


问题:

  1. 如何调整上面的代码来迭代所有元素,而不是只迭代第一个元素?
  2. 还有更优雅的方法吗? (只是寻找指针,不一定代表)

【问题讨论】:

  • 在嵌套的 for 循环中,您将 i 分配为 seq_along(inputs),然后将相同的 i 覆盖为 seq_along(files)。您需要为每个循环分配不同的向量。例如,将j 分配为seq_along(files) 并将所有files[[i]] 更改为files[[j]]。这可能会解决您的问题(我还没有尝试过)。

标签: r for-loop grepl nested-for-loop


【解决方案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来写入输入路径。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-15
  • 2013-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-10
  • 1970-01-01
相关资源
最近更新 更多