interseção entre 2 arquivos

3

Eu tenho um arquivo contendo dados SNP chamado snp.bed , que se parece com isto:

head snp.bed

    Chr17   214708483   214708484   Chr17:214708484
    Chr17   214708507   214708508   Chr17:214708508
    Chr17   214708573   214708574   Chr17:214708574

Eu também tenho um arquivo chamado intersect.bed , que é assim:

head intersect.bed

    Chr17   214708483   214708484   Chr17:214708484 Chr17   214706266   214710783   gene50573
    Chr17   214708507   214708508   Chr17:214708508 Chr17   214706266   214710783   gene50573
    Chr17   214708587   214708588   Chr17:214708580 Chr17   214706266   214710783   gene50573

Eu quero imprimir uma versão modificada de snp.bed , que contém uma coluna extra anexada a cada linha. Se uma linha em snp.bed corresponder às quatro primeiras colunas de uma linha em intersect.bed , eu quero imprimir a linha inteira de snp.bed com uma coluna extra obtida ao lado da última coluna da linha correspondente em intersect.bed (o nome do gene). Alternativamente, se uma linha de snp.bed não corresponder a nenhuma linha de intersect.bed , então junte-se a uma coluna extra que consiste na string "NA" em vez do nome do gene.

Esta é minha saída desejada:

head snp.matched.bed

    Chr17   214708483   214708484   Chr17:214708484   gene50573
    Chr17   214708507   214708508   Chr17:214708508   gene50573
    Chr17   214708573   214708574   Chr17:214708574   NA

Como posso fazer isso?

    
por Anna1364 06.11.2017 / 23:35

3 respostas

3

Esta solução assume que os arquivos não possuem espaços no início das linhas. O que é diferente dos seus exemplos, que possuem esses espaços.

awk '
{
    str = $1$2$3$4; 
}
FNR == NR {
    arr[str] = $NF;
}
FNR != NR {
    gene_name = arr[str] ? arr[str] : "NA";
    print $0, gene_name;
}' intersect.bed snp.bed 

Resultado

Chr17   214708483   214708484   Chr17:214708484 gene50573
Chr17   214708507   214708508   Chr17:214708508 gene50573
Chr17   214708573   214708574   Chr17:214708574 NA
    
por 07.11.2017 / 00:19
3

Aqui está uma solução usando o awk:

$ awk -F '\t' 'BEGIN{while(getline line<"intersect.bed") {N=split(line,a,"\t"); seen[a[1]"\t"a[2]"\t"a[3]"\t"a[4]]=a[N];}} {if(seen[$0]) {name=seen[$0];} else{name="NA"}; print $0 "\t" name}' snp.bed
Chr17       214708483       214708484       Chr17:214708484 gene50573
Chr17       214708507       214708508       Chr17:214708508 gene50573
Chr17       214708573       214708574       Chr17:214708574 NA

Estou assumindo caracteres de tabulação única como o delimitador de ambos os arquivos de entrada.

Note também que interpretei "primeira quarta coluna" como "primeiras quatro colunas".

    
por 06.11.2017 / 23:48
3

Pessoalmente, acho que para esse tipo de tarefa é melhor usar uma linguagem de programação "real". Eu gosto de Python, então aqui está um script Python que faz o que você quer (é intencionalmente detalhado para que você possa entendê-lo e modificá-lo facilmente):

#!/usr/bin/env python2

# intersect.py

# Read data from the first file
snp_rows = []
with open("snp.bed", 'r') as snp_file:
    for row in snp_file:
        snp_rows.append(row.split())

# Read data from the second file
int_rows = []
with open("intersect.bed", 'r') as int_file:
    for row in int_file:
        int_rows.append(row.split())

# Compare data and compute results
results = []
for row in int_rows:
    if row[:4] in snp_rows:
        results.append(row[:4] + [row[-1]])
    else:
        results.append(row[:4] + ["NA"])

# Print the results
for row in results:
    print(' '.join(row))

Salve-o em um arquivo e execute-o:

python2 intersect.py

E só por diversão, aqui está uma solução Bash usando comandos padrão (apenas grep e cut ):

while read row; do
    match="$(grep -F "${row}" intersect.bed)";
    if [[ -n "${match}" ]]; then
        echo "${row} $(echo ${match} | cut -d' ' -f8)";
    else
        echo "${row} NA";
    fi;
done < snp.bed

Observe que, em geral, não é recomendado usar o Bash para fazer um processamento de texto sério. Veja, por exemplo, o seguinte post:

por 06.11.2017 / 23:56