【问题标题】:LOOP on files ! PARSE FILES and GROUP them by IDENTIFIER?循环文件!解析文件并按 IDENTIFIER 分组?
【发布时间】:2021-11-10 20:27:19
【问题描述】:

我想:

  1. 从目录中读取 *.txt 文件列表

  2. 对于我文件夹中的所有 .txt 文件,我想使用所有行 id=NAME 中包含的信息,这是所有 *.txt 文件中第五列的一部分(例如,Hox.txt 和锌。 txt 下)

  3. 使用将 id 值链接到 Family 值的单独查找表(例如,下面的查找表)确定给定文件属于哪个系列(例如 cram-2)

  4. 将所有具有相同系列的文件(例如 HOX.txt 和 zinc.txt)合并/连接到一个 .txt 文件中。

  5. 使用列 Family 的名称保存链接文件(例如 cram-2.txt)。

!!提醒 !! !! R 将不得不处理大量繁重的 .txt 文件 - 需要临时目录吗? !!

例子:

HOX.txt 文件行:

ma  reg out fim id=HOX;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
se  reg out fim id=HOX;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
to  reg out fim id=HOX;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
pa  reg out fim id=HOX;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05

zinc.txt 文件行:

ma  reg out fim id=zinc;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
se  reg out fim id=zinc;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
to  reg out fim id=zinc;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
pa  reg out fim id=zinc;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05

查找表:

Name                        Family
HOX                         cram-2
zinc                        cram-2
fire                        sf.xr
fire                        ra.XS-2
...continues...

我搜索得到的最终输出:

a) 文件名 = cram-2.txt

b) 连接 HOX.txt 和 zinc.txt,因为它们都来自 Family cram-2!

ma  reg out fim id=HOX;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
se  reg out fim id=HOX;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
to  reg out fim id=HOX;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
pa  reg out fim id=HOX;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
ma  reg out fim id=zinc;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
se  reg out fim id=zinc;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
to  reg out fim id=zinc;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05
pa  reg out fim id=zinc;seq=AGCAGGAAATA;score=12.1915;pval=4.97e-05

代码只适用于少数文件。床。 我尝试使用 tempfile() 和 tempdir() 但仍然没有用。

dfNameFamily = tibble(
  Name = as.character(df$Name),  
  Family = as.character(df$Family)

dir = "~/textfiles"

TxtFile = function(dir) dir_ls(dir, regexp = "\\.txt$")

readTxt = function(FileName){
  lines = character()
  if(file_exists(FileName)){
    con = file(FileName, open = "r")
    lines = readLines(con)
    close(con)
  }
  lines
}

GetName = function(l) str_match(l, ";id=(.+);seq")[1,2]

SaveFile = function(l, name, dir){
  con = file(paste0(dir, "/" , name))
  writeLines(unlist(l$lines), con)
  close(con)
}

tibble(FileName = TxtFile(dir)) %>%  
  mutate(
    lines = map(FileName, readTxt),  
    Name = map_chr(lines, GetName)) %>%  
  left_join(dfNameFamily, by="Name") %>%  
  group_by(Family) %>%  
  group_walk(SaveFile, dir)  

【问题讨论】:

  • Stackoverflow 不是雇用某人为您编写代码的网站。你需要展示你到目前为止所做的事情,人们会很高兴找到答案并解决你遇到的确切问题。您可以在此处阅读有关如何提供MCVE

标签: r loops for-loop parsing


【解决方案1】:

试试这个代码。

将要处理的文件收集到bedDir 目录中。为输出文件创建一个目录bedOut。最好将其保存在您创建这些目录的一个 RStudio 项目中。

根据您的需要相应地扩展Names Families 向量。

library(data.table)
library(tidyverse)
library(fs)
library(utils)

Names = c("HOX", "zinc", "fire", "fire2")
Families = c("cram-2", "cram-2", "sf.xr", "ra.XS-2")
GetName = function(l) str_match(l, "id=(.+);seq")[1,2]
GetFamily = function(l) Families[which(Names==GetName(l))]

BedFile = function(dir) dir_ls(dir, regexp = "\\.bed$")

info = function(txt, start_time, end_time){
  tdif = end_time - start_time
  tunit = " ms"
  if(tdif>=1000){
    tdif = tdif/1000
    tunit = " s"
  }
  cat(paste0("Read ", txt," (", round(tdif,2),tunit,")\n"))
}

time_ms = function() as.numeric(as.numeric(Sys.time())*1000, digits=15)

pbTitle = function(path, files, i){
  paste("[", round(i/length(files)*100, 0),"%]",
        "files have been read from the", path, "directory.",
        "The file being read:", files[i])}

bedDir = "bedDir"
bedOut = "bedOut"
files = BedFile(bedDir)
if(length(files)>0){
  start_time = time_ms()
  pb = winProgressBar(max = length(files), width = 500)
  on.exit(close(pb), add = TRUE)

  for(i in 1:length(files)){
    setWinProgressBar(pb, i-1, pbTitle(bedDir, files, i-1))
    lines = fread(text = files[i], sep = "|", header=FALSE)
    Name = GetName(lines[1])
    Family = GetFamily(lines[1])
    fileName = paste0(bedOut, "/", Family, ".bad")
    fwrite(lines, fileName, append = file_exists(fileName))
  }

  close(pb)
  info(paste(length(files), "files"), start_time, time_ms())
}

附: 我建议您注意我使用了已知最快的函数来读取和写入来自data.table 包的fread fwrite 文本文件。

如果是这样,请告诉我它的运行速度。

【讨论】:

  • 在 10 分钟内完成了 137 Gbts。这真是太感谢你了! @MarekFiolka
  • 最重要的是要清楚问题。由于您已经了解他,您可以为他寻找最佳解决方案。您对问题的原始描述有些混乱和不完整。在编写程序的第一个版本时,我相当猜测您的期望。完全了解您的问题,我能够对其进行优化。希望你顺便学到了一些东西(确定txtProgressBar 是如何工作的)。最后,看看我的其他答案。也许其中之一对您来说同样有用,您会想要单击“这个答案很有用”。我会很高兴的。
  • 是的,它很有用,不过需要花一点时间来理解代码的每个部分。当然,我会仔细阅读您的其他意见和内容丰富的答案。最好的,再次感谢您! @MarekFiolka
猜你喜欢
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-19
  • 2021-10-17
相关资源
最近更新 更多