Eu tenho um arquivo chamado snp_data
contendoSNP (polimorfismo de nucleotídeo único)dados cromossômicos. Este é um arquivo CSV delimitado por espaços em branco de 3 colunas que possui o seguinte formato:
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
Observe que para cada linha o snp_id
campo possui o formato Chr{chromosome}__{position}
dos valores correspondentes de chromosome
e position
.
Tenho outro arquivo chamado window
contendo dados auxiliares. Este é um arquivo CSV delimitado por espaços em branco de 5 colunas que possui o seguinte formato:
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
Observe a correspondência entre os window
arquivos e snp_data
determinada pelo valor do chromosome
campo no window
arquivo e os valores dos campos chromosome
e snp_id
no snp_data
arquivo, por exemplo, linhas com valor "Chr1"
in window
correspondem a linhas in snp_data
com valor 1
for chromosome
e cujas snp_id
linhas começam com a prefixo de Chr01__
.
Para cada linha no snp_data
arquivo (cada snp dentro de cada cromossomo), se o valor dessa linha position
estiver dentro do intervalo fornecido pelos valores start
e end
de qualquer uma das linhas window
desse cromossomo específico, anexe o seqname
do window
arquivo à linha do snp_data
arquivo .
Para a entrada fornecida acima, esta seria a saída desejada:
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
O ponto principal é que as posições são únicas apenas dentro de cada cromossomo, então preciso comparar esses 2 arquivos cromossomo por cromossomo (ou seja, para cada cromossomo separadamente). Como posso fazer isso?
Responder1
Aqui está um script Python que deve fazer o que você deseja:
#!/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))
Observe que este script pressupõe que todas as suas linhas são linhas de dados. Se seus arquivos de entrada forem nomeados snp_data
, window
você poderá executá-los assim:
python intersect_snp.py snp_data window
Se seus arquivos tiverem linhas de cabeçalho, você poderá tail
pular/remover os cabeçalhos e executá-los assim:
python intersect_snp.py <(tail -n+2 snp_data) <(tail -n+2 window)
Suponha que este seja o seu snp_data
arquivo:
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
E que este é o seu window
arquivo:
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
Então, se executarmos este comando:
python intersect_snp.py <(tail -n+2 snp_data) <(tail -n+2 window)
Obtemos a seguinte saída:
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
Responder2
Para evitar grandes tempos de espera, você pode fazer isso com o mecanismo SQL minimalista SQLite que é frequentemente pré-instalado no Linux. Ele não executa um servidor e funciona com bancos de dados SQL armazenados em arquivos.
No seu diretório snp_data & window faça:
cat snp_data | tr -s " " > snp_data.csv
sed 's#Chr##g' window | tr -s " " > window.csv
Isso normaliza os espaços entre os campos e os prepara para importação.
Em seguida, importe esses dados para SQL e execute a consulta para obter a saída:
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 aqui para interromper a entrada]
E finalmente:
cat task.sql | sqlite3 my_database.db
Em geral, isso deve ser mais rápido para arquivos grandes.