【问题标题】:R: locating files that their names contain a specific string from a directory and match to my list of wanted filesR:查找名称包含目录中特定字符串并与我的所需文件列表匹配的文件
【发布时间】:2020-06-04 05:03:04
【问题描述】:

又是我的新手,文件和文件夹乱七八糟(感谢我们的生物学家):我得到了这个目录,其中包含大量 .txt 文件(~900,000+),所有文件以前都以不一致的命名方式提交格式:(

例如,目录中的杂乱文件如下所示:

ctrl_S978765_uns_dummy_00_none.txt
ctrl_S978765_3S_Cookie_00_none.txt
S59607_3S_goody_3M_V10.txt
ctrlnuc30-100_S3245678_DMSO_00_none.txt
ctrlRAP_S0846567_3S_Dex_none.txt
S6498432_2S_Fulra_30mM_V100.txt
.....

如您所见,命名没有可靠的一致性。对我来说重要的是嵌入其中的 ID 代码,例如 S978765。现在我得到了我想要的这些 ID 代码的列表(100 个 ID 代码)。

包含以下列表的 CSV 文件,请注意,由于第二列中的 CLnumber 值不同,该列表在行中确实有重复的 ID 代码:

ID code  CLnumber
S978765  1
S978765  2
S306223  1
S897458  1
S514486  2
....

所以我想完成以下任务:通过匹配我的列表,使用代码 ID 找到所有凌乱的命名文件。并将它们复制到一个新目录中。

我曾想过使用 list.files() 来获取所有 .txt 文件及其名称,然后我在下一步匹配代码 ID 名称时遇到了困难,我知道如何用一个字符串来做到这一点,比如说“S978765”,但如果我一个一个地做,这几乎就像手动挖文件夹一样。

如何将 column1 中的 ID 代码名称作为列表提供,并将它们与目录中凌乱的文件标题名称进行比较/匹配,然后将它们复制到新文件夹中?

非常感谢, 机器学习

【问题讨论】:

    标签: r string-matching


    【解决方案1】:

    这行得通:

    library(stringr)
    
    # get this via list.files in your actual code
    files <- c("ctrl_S978765_uns_dummy_00_none.txt",
               "ctrl_S978765_3S_Cookie_00_none.txt",
               "S59607_3S_goody_3M_V10.txt",
               "ctrlnuc30-100_S3245678_DMSO_00_none.txt",
               "ctrlRAP_S0846567_3S_Dex_none.txt",
               "S6498432_2S_Fulra_30mM_V100.txt")
    
    ids <- data.frame(`ID Code` = c("S978765", "S978765", "S306223", "S897458", "S514486"),
                      CLnumber = c(1, 2, 1, 1, 2),
                      stringsAsFactors = FALSE)
    
    str_subset(files, paste(ids$ID.Code, collapse = "|"))
    #> [1] "ctrl_S978765_uns_dummy_00_none.txt" "ctrl_S978765_3S_Cookie_00_none.txt"
    

    str_subset 接受一个字符向量并返回匹配某个模式的元素。在本例中,模式为"S978765|S978765|S306223|S897458|S514486"(使用paste 创建),它是一个正则表达式,它匹配任何由| 分隔的ID 代码。所以我们取files 并只保留ID Code 中匹配的元素。

    还有很多其他方法可以做到这一点,可能会也可能不会更清楚。例如,您可以将ids$ID.Code 直接传递给str_subset,而不是通过paste 构造正则表达式,但这会每次都抛出关于对象长度的警告,这可能会让人感到困惑(或者如果你习惯了会导致问题忽略它,然后在重要的不同上下文中忽略它)。另一种方法是使用purrrkeep,虽然这样写起来可能更清楚一点,但效率会低很多,因为这意味着要对文件向量进行多次传递——与这个上下文,但如果您突然需要对数十万个文件和 ID 执行此操作,则可能非常相关。

    【讨论】:

    • 谢谢,我已经尝试了代码并对其进行了修改,以使用 list.files 提取完整的文件名并使文件名成为矩阵。 str_subset 很棒。但是,既然我有一个名为“matched”的新矩阵,它存储 str_subset,我如何将实际文件复制并粘贴到单独的目录中?
    • 哈哈,我结合了 Ronak Shah 的 file.copy 建议,现在效果很好。谢谢你们!
    • 我真的很喜欢你解释这个函数是如何工作的!伙计,你应该有一个 YouTube 频道
    【解决方案2】:

    您可以使用正则表达式从文件名中提取 ID 代码。

    在这里,我使用了模式“S”后跟 5 个或更多数字。一旦我们提取了 ID_codes,我们就可以将它们与我们在 csv 中的那些进行比较。

    假设 csv 被称为 df 并且列名是 ID_Codes 我们可以使用 %in% 来过滤它们。

    然后我们可以使用file.copy 将文件从一个文件夹移动到另一个文件夹。

    all_files <- list.files(path = '/Path/To/Folder', full.names = TRUE)
    selected_files <- all_files[sub('.*(S\\d{5,}).*', '\\1', basename(all_files)) 
                                     %in% unique(df$ID_Codes)]
    file.copy(selected_files, 'new_path/for/files')
    

    【讨论】:

    • 谢谢!抱歉,我在上面的帖子之后看到了您的帖子,但是您的 file.copy 建议实际上可以用来连接到它以实际完成工作。让我现在试试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-10
    • 2014-12-23
    • 2019-04-28
    • 1970-01-01
    • 2018-10-06
    • 2022-01-17
    相关资源
    最近更新 更多