Удалить несколько последовательностей из файла FASTA - PullRequest
2 голосов
/ 11 апреля 2019

У меня есть текстовый файл последовательностей символов, который состоит из двух строк: заголовка и самой последовательности в следующей строке.Структура файла выглядит следующим образом:

>header1
aaaaaaaaa
>header2
bbbbbbbbbbb
>header3
aaabbbaaaa
[...]
>headerN
aaabbaabaa

В другом файле у меня есть список заголовков последовательностей, которые я хотел бы удалить, например:

>header1
>header5
>header12
[...]
>header145

Идея состоит в том, чтобы удалить эти последовательности из первого файла, поэтому все эти заголовки + следующая строка.Я сделал это с помощью sed, как показано ниже:

while read line; do sed -i "/$line/,+1d" first_file.txt; done < second_file.txt

Это работает, но занимает довольно много времени, так как я загружаю весь файл несколько раз с помощью sed, и он довольно большой.Любая идея о том, как я мог бы ускорить этот процесс?

Ответы [ 7 ]

1 голос
/ 11 апреля 2019

На ваш вопрос легко ответить, но он не поможет вам, когда вы работаете с обычными fast-файлами. Файлы Fasta имеют заголовок последовательности, за которым следуют одна или несколько строк, которые можно объединить для представления последовательности. Формат файла Fasta примерно соответствует следующим правилам:

  • Строка описания (defline) или строка заголовка / идентификатора, которая начинается с символа «more-then» (>), дает имя и / или уникальный идентификатор последовательности и может также содержать дополнительную информацию.
  • После строки описания указывается фактическая последовательность в стандартной однобуквенной символьной строке. Все, кроме допустимого символа, будет игнорироваться (включая пробелы, табуляторы, звездочки и т. Д.).
  • Последовательность может занимать несколько строк.
  • Формат FASTA с несколькими последовательностями можно получить путем объединения нескольких файлов FASTA с одной последовательностью в общий файл, обычно оставляя пустую строку между двумя последующими последовательностями.

Большинство из представленных методов не работают в мульти-фасте с многострочными последовательностями

Всегда будет работать следующее:

awk '(NR==FNR) { toRemove[$1]; next }
     /^>/ { p=1; for(h in toRemove) if ( h ~ $0) p=0 }
    p' headers.txt file.fasta

Это очень похоже на ответы EdMorton и Anubahuva , но разница здесь в том, что файл headers.txt может содержать только часть заголовка.

1 голос
/ 11 апреля 2019

Вы можете использовать это awk:

awk 'NR == FNR{seen[$0]; next} /^>/{p = !($0 in seen)} p' hdr.txt details.txt
1 голос
/ 11 апреля 2019
$ awk 'NR==FNR{a[$0];next} $0 in a{c=2} !(c&&c--)' list file
>header2
bbbbbbbbbbb
>header3
aaabbbaaaa
[...]
>headerN
aaabbaabaa

c - это количество строк, которые вы хотите пропустить, начиная с той, которая только что совпала. Смотри https://stackoverflow.com/a/17914105/1745001.

В качестве альтернативы:

$ awk 'NR==FNR{a[$0];next} /^>/{f=($0 in a ? 1 : 0)} !f' list file
>header2
bbbbbbbbbbb
>header3
aaabbbaaaa
[...]
>headerN
aaabbaabaa

f указывает, была ли найдена самая последняя прочитанная строка >... в целевом массиве a[]. f=($0 in a ? 1 : 0) может быть сокращено до f=($0 in a), но я предпочитаю троичное выражение для ясности.

Первый скрипт полагается на то, что вы знаете, сколько строк занимает каждая запись, а второй - на каждой записи, начинающейся с >. Если вы знаете и то, и другое, то какой из них вы используете, это выбор стиля.

0 голосов
/ 12 апреля 2019

попробуй гну сед,

sed -E ':s $!N;s/\n/\|/;ts ;s~.*~/&/\{N;d\}~' second_file.txt| sed -E -f -  first_file.txt

prepend time команда для обоих сценариев для сравнения скорости,
посмотрите time while read line;do... и time sed -.... результат в моем тесте, это сделано менее чем за половину времени ОП

0 голосов
/ 11 апреля 2019

Это awk может работать для вас:

awk 'FNR==NR{a[$0]=1;next}a[$0]{getline;next}1' input2 input1
0 голосов
/ 11 апреля 2019

Создать скрипт с командами удаления из второго файла:

sed 's#\(.*\)#/\1/,+1d#' secondFile.txt > commands.sed

Затем примените этот файл к первому

sed -f commands.sed firstFile.txt 
0 голосов
/ 11 апреля 2019

Один из вариантов - создать длинное выражение sed:

sedcmd=
while read line; do sedcmd+="/^$line\$/,+1d;"; done < second_file.txt
echo "sedcmd:$sedcmd"
sed $sedcmd first_file.txt

. Файл будет прочитан только один раз.Обратите внимание, что я добавил ^ и $ в шаблон sed (поэтому >header1 не соответствует >header123 ...)


Использование файла (как подсказывает @daniu)может быть лучше, если у вас есть тысячи файлов, так как вы рискуете достичь максимального числа команд в командной строке с помощью этого метода.

...