использование awk для исключения диапазона строк из одного файла, зависящего от второго файла

#awk

#awk

Вопрос:

У меня есть два файла — файл один содержит число (1-22) в столбце 1 и диапазон от нижнего числа (столбец 2) и верхнего числа (столбец 3). Вот первая пара строк:

1 11362778 12362778
1 22054176 23054176
1 28191734 29191734
1 42956767 43956767
1 65941329 66941329

У первого файла нет заголовка.

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

SNP CHR BP
rs115828134 1 11363041
rs2788537 1 11363231
rs12141932 1 11363301

Что я хочу сделать, так это удалить все строки в файле 2, если столбец 2 в файле 2 равен столбцу 1 в файле 1, И если столбец 3 в файле 2 попадает в диапазон столбцов 2 и 3 в файле 2.

По сути, что-то вроде этого:, но перебирает все строки файла 1.

 awk '{if($2==1 amp;amp; $3 < 11362778 || $3 > 12362778) print $0}' file 2 > results.txt 
 

Ответ №1:

Я согласен на 100% с @jared_mamrot, используйте для этого надлежащие инструменты bioinfo.

Тем не менее, есть способ подойти к этому с помощью awk. Но обязательно протестируйте это на реальном наборе данных, прежде чем полагаться на него для серьезной науки, поскольку я не совсем уверен, охватывает ли он все угловые случаи, особенно в вашем ограниченном примере.

Данные (добавлены совпадающие данные):

 $ cat file1
1       11362778        12362778
1       22054176        23054176
1       28191734        29191734
1       42956767        43956767
1       65941329        66941329
2       42956767        43956767
2       65941329        66941329

$ cat file2
SNP     CHR     BP
rs10875231      1       100000012
rs6678176       1       100000827
rs78286437      1       100000843
rr234233        1       29000000
rr453654        1       29000120
e34534534       1       23444444
rs144406489     1       100001138
rr564564        2       29000120
e34534534       2       23444444
rs144406489     2       42956775 
 

Используйте:

 $ awk 'NR==FNR{ chr[NR]=$1; x[NR]=$2; y[NR]=$3; en=NR }
       NR!=FNR{ set=0;
                for(i=1;i<=en;i  ){
                  if(chr[i]==$2 amp;amp; ( $3 <= y[i] amp;amp; $3 >= x[i] ) ){
                    set=0; break
                  }
                  else{ set=1 }
                }
                if(set==1){ print }
      }' file1 file2
 

Вывод:

 SNP     CHR     BP
rs10875231      1       100000012
rs6678176       1       100000827
rs78286437      1       100000843
e34534534       1       23444444
rs144406489     1       100001138
rr564564        2       29000120
e34534534       2       23444444 
 

Ответ №2:

Этот тип вопросов, зависящих от домена, лучше подходит для https://bioinformatics.stackexchange.com /

Сказав это, одним из возможных решений является преобразование второго файла в формат bed (такой же, как файл 1), а затем использование bedtools для выявления и исключения совпадений.

Сначала измените первую строку в file_1 так, чтобы координаты соответствовали записи в file_2, иначе вы не сможете увидеть, работает ли метод:

File_1.bed:

 1   100000011   100000014
1   22054176    23054176
1   28191734    29191734
1   42956767    43956767
1   65941329    66941329
 

File_2.bed

 # generated using
# awk 'NR>1 {print $2 "t" $3 "t" $3 "t" $1}' file_2 > file_2.bed
1   100000012   100000012   rs10875231
1   100000827   100000827   rs6678176
1   100000843   100000843   rs78286437
1   100001138   100001138   rs144406489
 

Используйте bedtools intersect для идентификации и удаления пересекающихся записей:

 bedtools intersect -v -a file_2.bed -b file_1.bed
 

Вывод:

 1   100000827   100000827   rs6678176
1   100000843   100000843   rs78286437
1   100001138   100001138   rs144406489
 

Комментарии:

1. Спасибо! Yup- bedtools работает, просто хочу иметь возможность записать его как awk

Ответ №3:

что-то подобное должно работать, но у вас нет проверяемого ввода, поэтому не проверено (нет перекрытия в диапазонах!).

 $ awk 'NR==FNR {c[$1]  ; b[$1,c[$1]]=$2; e[$1,c[$1]]=$3; next}
       $2 in c {for(i=1;i<=c[$2];i  ) 
                  if(b[$2,i]<$3 amp;amp; $3<e[$2,i]) next}1' file1 file2
 

также, пожалуйста, отправьте образец ввода, чтобы его можно было скопировать / вставить для удобства тестирования.

Использование примеров входных данных из ответа @AndreWildberg и конвейера column дает

 $ awk ... | column -t

SNP          CHR  BP
rs10875231   1    100000012
rs6678176    1    100000827
rs78286437   1    100000843
e34534534    1    23444444
rs144406489  1    100001138
rr564564     2    29000120
e34534534    2    23444444
 

Обратите внимание, что это должно работать немного быстрее, чем альтернатива, поскольку сканирование перекрытия ограничено только совпадающими кодами. В зависимости от вашего размера ввода он может быть незначительным или нет.

Комментарии:

1. Спасибо — Похоже, что он выполняет противоположное тому, что нужно, т.Е. печатает всю строку, которую я хочу удалить. Я обновил файл 2 выше

2. Я хотел бы, чтобы в файле отсутствовали области файла 1

3. Хорошо, я неправильно понял. Обновлено, чтобы пропустить вместо печати.