Вопрос по оптимизации: использование словаря из файла 1 для преобразования файла 2

#python #bash #optimization #awk

#python #bash #оптимизация #awk

Вопрос:

Я пытаюсь преобразовать файл 1 (файл gtf, если какой-либо биоинформатик проходит мимо) со строками типа:

 1   X   exon    1   300000  1000    -   .   gene_id "Z.633"; transcript_id "Z.633.mrna1"; exon_number "1"; 
1   X   transcript  1   300000  1000    -   .   gene_id "Z.633"; transcript_id "Z.633.mrna1"; 
1   X   exon    300005  300500  1000    -   .   gene_id "Y.6330"; transcript_id "Y.6330.mrna1"; exon_number "2";
1   X   exon    300500  310000  1000        .   gene_id "Y.6330"; transcript_id "Y.6330.mrna1"; exon_number "1"; 
1   X   transcript  30005   310000  1000        .   gene_id "Y.6330"; transcript_id "Y.6330.mrna1";
  

в файл, в котором все «Z» будут заменены на «F», и другие соответствия. Все соответствия находятся в файле 2, который я использую в качестве словаря, столбец 1 — это ключи, столбец 2 — значения.

пример файла 2:

 Z.633 F.633
Y.6330 U.6330
  

пример результата :

 1   X   exon    1   300000  1000    -   .   gene_id "F.633"; transcript_id "F.633.mrna1"; exon_number "1"; 
1   X   transcript  1   300000  1000    -   .   gene_id "F.633"; transcript_id "F.633.mrna1"; 
1   X   exon    300005  300500  1000    -   .   gene_id "U.6330"; transcript_id "U.6330.mrna1"; exon_number "2";
1   X   exon    300500  310000  1000        .   gene_id "U.6330"; transcript_id "U.6330.mrna1"; exon_number "1"; 
1   X   transcript  30005   310000  1000        .   gene_id "U.6330"; transcript_id "U.6330.mrna1";
  

файл 1 содержит около 200000 строк, а файл 2 — 20000.

Для этого я использовал awk-скрипт:

 NR == FNR {
  rep[ $2 ] = $1 
  next
} 

{
  for (key in rep)
    gsub(key, rep[key])
  print
}

  

и затем:

 awk -f dict.awk file2 file1 > newfile
  

Моя проблема в том, что скрипт фактически выполняется в течение нескольких дней… Есть ли какой-либо способ, которым я мог бы это улучшить?
Есть ли более подходящий язык программирования для этой проблемы? (Я пробовал python, но время выполнения было еще хуже)

(использовался скрипт на python:)

 def replaceWithDictionnary(dictFileName,fileToReplaceName,newFileName):
    import re
    with open(dictFileName,'r') as d:
        dictFile = dict((line.strip().split())[::-1] for line in d)
        
    with open(newFileName,'w') as g:
        with open(fileToReplaceName,'r') as f:
            for line in f.readlines():
                for d_key, d_value in dictFile.items():
                    if bool(re.search(d_key "D ", line)):
                    #if """ d_key """ in line:
                        #print(d_key)
                        newline=line.replace(d_key,d_value)
                        #print(d_value)
                        g.write(newline)
                        continue
  

Я могу сказать, что это не та часть словаря, которая занимает так много времени, потому что я тестировал ее с меньшим файлом1, и она выполнялась быстро…

Ответ №1:

Предполагая, что для каждой записи требуется заменить только одну gene_id функцию, которую всегда можно найти в 10-м столбце, как в вашем примере файла, вы можете найти ее и вызвать gsub один раз, вместо вызова 20 тысяч функций для каждой записи.

 > cat tst.awk
NR==FNR {
  r[$1] = $2
  next
}

{
  x = $10
  gsub(/"|;/, "", x)   
  gsub(x, r[x])
  print
}
  

 awk -f tst.awk file2 file1