Tengo un archivo llamado snp_data
que contieneSNP (polimorfismo de un solo nucleótido)datos cromosómicos. Este es un archivo CSV de 3 columnas, delimitado por espacios en blanco, que tiene el siguiente 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
Tenga en cuenta que para cada fila el snp_id
campo tiene el formulario Chr{chromosome}__{position}
para los valores correspondientes de chromosome
y position
.
Tengo otro archivo llamado window
que contiene datos auxiliares. Este es un archivo CSV de 5 columnas, delimitado por espacios en blanco, que tiene el siguiente 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
Tenga en cuenta la correspondencia entre los window
archivos snp_data
y determinada por el valor del chromosome
campo en el window
archivo y los valores de los campos chromosome
y snp_id
en el snp_data
archivo, por ejemplo, las filas con un valor de "Chr1"
in window
corresponden a filas snp_data
con un valor de 1
for chromosome
y cuyas snp_id
filas comienzan con un prefijo de Chr01__
.
Para cada fila del snp_data
archivo (cada snp dentro de cada cromosoma), si el valor de esa fila position
se encuentra dentro del rango dado por los valores start
y end
de cualquiera de las filas window
para ese cromosoma en particular, agregue el seqname
del window
archivo a la fila del snp_data
archivo. .
Para la entrada proporcionada anteriormente, este sería el resultado deseado:
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
El punto principal es que las posiciones son únicas sólo dentro de cada cromosoma, por lo que necesito comparar estos 2 archivos cromosoma por cromosoma (es decir, para cada cromosoma por separado). ¿Cómo puedo hacer esto?
Respuesta1
Aquí hay un script de Python que debería hacer lo que quieras:
#!/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))
Tenga en cuenta que este script supone que todas sus filas son filas de datos. Si sus archivos de entrada tienen nombre snp_data
, window
puede ejecutarlos así:
python intersect_snp.py snp_data window
Si sus archivos tienen filas de encabezado, puede utilizar tail
para omitir/eliminar los encabezados y ejecutarlo de esta manera:
python intersect_snp.py <(tail -n+2 snp_data) <(tail -n+2 window)
Supongamos que este es su snp_data
archivo:
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
Y que este es tu window
archivo:
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
Entonces si ejecutamos este comando:
python intersect_snp.py <(tail -n+2 snp_data) <(tail -n+2 window)
Obtenemos el siguiente resultado:
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
Respuesta2
Para evitar grandes tiempos de espera, puede hacerlo con el motor SQL minimalista SQLite que suele estar preinstalado en Linux. No ejecuta un servidor y funciona con bases de datos SQL que se almacenan en archivos.
En su directorio snp_data & window haga:
cat snp_data | tr -s " " > snp_data.csv
sed 's#Chr##g' window | tr -s " " > window.csv
Esto normaliza los espacios entre campos y los prepara para la importación.
Luego importe estos datos a SQL y ejecute la consulta para obtener el resultado:
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 aquí para detener la entrada]
Y finalmente:
cat task.sql | sqlite3 my_database.db
En general, esto debería ser más rápido para archivos grandes.