У меня есть файл с именем, snp_data
содержащийSNP (однонуклеотидный полиморфизм)Данные хромосом. Это CSV-файл с тремя столбцами, разделенными пробелами, который имеет следующий формат:
user@host:~$ cat snp_data
snp_id chromosome position
Chr01__912 1 912 1
Chr01__944 1 944 1
Chr01__1107 1 1107 1
Chr01__1118 1 1118 1
Chr01__1146 1 1146 1
Chr01__1160 1 1160 1
...
...
...
Chr17__214708367 17 214708367
Chr17__214708424 17 214708424
Chr17__214708451 17 214708451
Chr17__214708484 17 214708484
Chr17__214708508 17 214708508
Обратите внимание, что для каждой строки snp_id
поле имеет форму Chr{chromosome}__{position}
для соответствующих значений chromosome
и position
.
У меня есть еще один файл с именем, window
содержащий вспомогательные данные. Это 5-колоночный CSV-файл с разделителями-пробелами, который имеет следующий формат:
user@host:~$ cat window
seqname chromosome start end width
1 Chr1 1 15000 15000
2 Chr1 15001 30000 15000
3 Chr1 30001 45000 15000
4 Chr1 45001 60000 15000
5 Chr1 60001 75000 15000
6 Chr1 75001 90000 15000
...
...
...
199954 Chr17 214620001 214635000 15000
199955 Chr17 214635001 214650000 15000
199956 Chr17 214650001 214665000 15000
199957 Chr17 214665001 214680000 15000
199958 Chr17 214680001 214695000 15000
199959 Chr17 214695001 214708580 13580
Обратите внимание на соответствие между файлами window
и , snp_data
определяемое значением поля chromosome
в window
файле и значениями полей chromosome
и snp_id
в snp_data
файле, например, строки со значением "Chr1"
в window
соответствуют строкам в snp_data
со значением 1
для chromosome
и , строки которых snp_id
начинаются с префикса Chr01__
.
Для каждой строки в snp_data
файле (каждого snp в каждой хромосоме), если значение этой строки position
попадает в диапазон, заданный значениями start
и end
любой из строк window
для этой конкретной хромосомы, то добавить seqname
из window
файла к строке из файла snp_data
.
Для приведенных выше входных данных я бы хотел получить следующий результат:
user@host:~$ cat desired_output
snp_id chromosome position window
Chr01__912 1 912 1
Chr01__944 1 944 1
Chr01__1107 1 1107 1
...
...
...
Chr17__214708367 17 214708367 199959
Chr17__214708424 17 214708424 199959
Chr17__214708451 17 214708451 199959
Chr17__214708484 17 214708484 199959
Chr17__214708508 17 214708508 199959
Суть в том, что позиции уникальны только в пределах каждой хромосомы, поэтому мне нужно сравнить эти 2 файла хромосома за хромосомой (т.е. для каждой хромосомы отдельно). Как это сделать?
решение1
Вот скрипт на Python, который должен сделать то, что вам нужно:
#!/usr/bin/env python2
# -*- coding: ascii -*-
"""intersect_snp.py"""
import sys
# Read data from the SNP file into a list
snp_list = []
with open(sys.argv[1], 'r') as snp_file:
for line in snp_file:
snp_row = line.split()
snp_list.append(snp_row)
# Read data from the "window" file into a dictionary of lists
win_dict = {}
with open(sys.argv[2], 'r') as win_file:
for line in win_file:
seqnames, chromosome, start, end, width = win_row = line.split()
if chromosome not in win_dict:
win_dict[chromosome] = []
win_dict[chromosome].append(win_row)
# Compare data and compute results
results = []
# Iterate over snp data rows
for snp_row in snp_list:
# Extract the field values for each snp row
snp_id, chromosome, position = snp_row
# Convert the chromosome to match the format in the "window" file
# i.e. `1` -> `Chr1`
chromosome_name = "Chr{}".format(chromosome)
# Iterate over the "window" rows corresponding to that chromosome
for win_row in win_dict.get(chromosome_name, []):
# Extract the field values for each "window" row
seqnames, chromosome, start, end, width = win_row
# Perform the desired comparison
if int(start) <= int(position) <= int(end):
# If the comparison returns true, construct the result row
result = [snp_id, chromosome, position, seqnames]
results.append(result)
break
# Print the output column headers
columns = ["snp_id", "chromosome", "position", "window"]
print(" ".join(columns))
# Print the results
for row in results:
print(' '.join(row))
Обратите внимание, что этот скрипт предполагает, что все ваши строки являются строками данных. Если ваши входные файлы именованы snp_data
, window
то вы можете выполнить его следующим образом:
python intersect_snp.py snp_data window
Если в ваших файлах есть строки заголовков, то вы можете tail
пропустить/удалить заголовки и выполнить их следующим образом:
python intersect_snp.py <(tail -n+2 snp_data) <(tail -n+2 window)
Предположим, что это ваш snp_data
файл:
snp_id chromosome position
Chr01__912 1 912
Chr01__944 1 944
Chr01__1107 1 1107
...
...
...
Chr17__214708367 17 214708367
Chr17__214708424 17 214708424
Chr17__214708451 17 214708451
Chr17__214708484 17 214708484
Chr17__214708508 17 214708508
И это ваш window
файл:
seqnames chromosome start end width
1 Chr1 1 15000 15000
2 Chr1 15001 30000 15000
3 Chr1 30001 45000 15000
4 Chr1 45001 60000 15000
5 Chr1 60001 75000 15000
...
...
...
199954 Chr17 214620001 214635000 15000
199955 Chr17 214635001 214650000 15000
199956 Chr17 214650001 214665000 15000
199957 Chr17 214665001 214680000 15000
199958 Chr17 214680001 214695000 15000
199959 Chr17 214695001 214708580 13580
Затем, если мы выполним эту команду:
python intersect_snp.py <(tail -n+2 snp_data) <(tail -n+2 window)
Получаем следующий вывод:
snp_id chromosome position window
Chr01__912 Chr1 912 1
Chr01__944 Chr1 944 1
Chr01__1107 Chr1 1107 1
...
...
...
Chr17__214708367 Chr17 214708367 199959
Chr17__214708424 Chr17 214708424 199959
Chr17__214708451 Chr17 214708451 199959
Chr17__214708484 Chr17 214708484 199959
Chr17__214708508 Chr17 214708508 199959
решение2
Чтобы избежать большого времени ожидания, вы можете сделать это с помощью минималистичного SQL-движка SQLite, который часто предустанавливается в Linux. Он не запускает сервер и работает с базами данных SQL, которые хранятся в файлах.
В каталоге snp_data и window выполните:
cat snp_data | tr -s " " > snp_data.csv
sed 's#Chr##g' window | tr -s " " > window.csv
Это нормализует пробелы между полями и подготавливает их к импорту.
Затем импортируйте эти данные в SQL и выполните запрос, чтобы получить вывод:
cat > task.sql
CREATE TABLE snp_data (snp_id text,chromosome int, position int);
CREATE TABLE window (seqname int,chromosome int, c_start int , c_end int, c_width int);
.mode csv
.separator " "
.import snp_data.csv snp_data
.import window.csv window
.mode column
.header on
SELECT D.snp_id, D.chromosome, D.position, W.seqname FROM snp_data D, window W WHERE W.chromosome=D.chromosome AND D.position BETWEN W.c_start AND W.c_end;
[CTRL+D здесь для остановки ввода]
И наконец:
cat task.sql | sqlite3 my_database.db
В целом, для больших файлов это должно быть быстрее.