Оцените, находится ли значение столбца в диапазоне от 2 других столбцов, и распечатайте с помощью awk

#awk

Вопрос:

У меня есть два файла.

Файл 1 (сокращенный):

 1       1:135982[b38]A,G        0       12500   A       G
1       1:611317[b38]A,G        0       611317  A       G
1       1:722408[b38]G,C        0       722408  G       C
1       1:726649[b38]G,A        0       726649  G       A
 

Файл 2 (сокращенный):

 ENSG00000223972 ENST00000456328 DDX11L1    1       11869   14409
ENSG00000223972 ENST00000450305 DDX11L1    1       11869   14409
ENSG00000227232 ENST00000488147 WASH7P     1       14404   29570
 

Я хочу создать новый файл, в котором:

  • если столбец 1 в файле 1 соответствует столбцу 4 файла 2
  • И столбец 4 файла 1 находится в диапазоне столбцов 5 и 6 файла 2

Распечатайте столбец 3 файла 2 и столбец 2 файла 1.

Пример:

Для первой строки файла 1 столбец 1 (1) соответствует столбцу 4 файла 2 (также 1), А столбец 4 файла 1 (12500) равен >= 11869 и >:

 DDX11L1   1:134982[b38]A,G
 

В этом примере других совпадений не существует, так что это был бы единственный результат.

Как я могу сделать это с помощью awk?

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

1. Насколько велики файлы? Они отсортированы? Вы смотрите на время выполнения O(m*n) и потенциально значительное использование памяти, если вы не можете оптимизировать. Такого рода вещи тривиально реализуются в виде sql-запроса (sqlite может читать csv-файлы).

2. Не думал об этом. Да, это невозможно, файлы довольно большие. Сразу подумал о SQL как о первом ресурсе, но хотел знать, есть ли решение awk.

3. Я думаю, что с awk вам придется либо хранить весь один файл в памяти, либо перечитывать его снова и снова. Вероятно, довольно медленно, если это не укладывается в память. SQL может быть достаточно быстрым без изменений; если нет, создание явных индексов может ускорить процесс.

Ответ №1:

Не awk, но тривиально с sqlite:

 #!/bin/bash

# convert spaces to tabs
tr -s ' t' 't' <file1.raw >file1.tsv
tr -s ' t' 't' <file2.raw >file2.tsv

sqlite3 >output.tsv <<'EOD'
create table t1 (c1,c2,c3,c4 int,c5,c6);
create table t2 (c1,c2,c3,c4,c5 int,c6 int);
.mode tabs
.import file1.tsv t1
.import file2.tsv t2
select distinct t2.c3, t1.c2 from t1,t2
where t1.c1=t2.c4 and t1.c4 between t2.c5 and t2.c6;
EOD
 

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

1. Это не работает. Например, первая строка вывода DDX11L1 1:135982[b38]A,G . 135982 не находится между 11869 и 14409. Он также размещает то же 1:135982[b38]A,G самое с другими строками из другого файла, которые также имеют совершенно другие координаты. Для контекста DDX11L1-это ген, который охватывает определенное пространство, а другое дело-мутация, которая находится только в одном месте. Не может быть присвоено более чем одному гену.

2. Я изменил сценарий, чтобы привести числовые столбцы в виде целых чисел, и, похоже, теперь он работает.