combina dois arquivos em um único arquivo com colunas combinadas

2

Eu preciso combinar dois arquivos em um único arquivo com todas as colunas dos dois arquivos.

Estou fornecendo meus arquivos de exemplo. Arquivo 1

chr loc T1  C1
chr1    100 2   3
chr1    200 3   4
chr2    100 1   4
chr2    400 3   1

Arquivo 2

chr loc T2  C2
chr1    100 1   2
chr1    300 4   1
chr2    100 7   5
chr2    500 1   9

e o arquivo de saída deve ser assim

arquivo de saída

chr loc T1  C1  T2  C2
chr1    100 2   3   1   2
chr1    200 3   4   0   0
chr1    300 0   0   4   1
chr2    100 1   4   7   5
chr2    400 3   1   0   0
chr2    500 0   0   1   9
    
por Naresh DJ 16.07.2015 / 22:52

1 resposta

5
join -a1 -a2 -e 0 -o 0,1.2,1.3,2.2,2.3 \
    <(sed 's/ \+/_/' file1 | sort) \
    <(sed 's/ \+/_/' file2 | sort) | 
sed 's/_/ /' | 
column  -t | 
sort
chr   loc  T1  C1  T2  C2
chr1  100  2   3   1   2
chr1  200  3   4   0   0
chr1  300  0   0   4   1
chr2  100  1   4   7   5
chr2  400  3   1   0   0
chr2  500  0   0   1   9

A parte mais complicada aqui são as razões pelas quais sed - join se unirá em um único campo, e aqui os critérios de associação são os dois primeiros campos. Então, temos que combinar esses campos em uma única palavra: eu substituo a primeira seqüência de espaço em branco por um sublinhado, então a junção verá chr1_100 , chr1_200 , etc.

join requer que seus arquivos de entrada sejam classificados.

Eu uso substituição de processos para que join possa trabalhar com o sed|sort pipelines como arquivos.

Em seguida, outra chamada sed para desfazer o campo combinado e, em seguida, column para torná-lo bonito.

Por padrão, join usa o primeiro campo de cada arquivo como o campo-chave.

Por padrão, join faz uma junção interna : somente chaves presentes em ambos os arquivos são impressos. A opção -a1 e -a2 ativa a junção externa completa desejada. A opção -e fornece o valor padrão para campos nulos e precisamos que a opção -o especifique que queremos todos os campos.

Também pode usar o awk:

awk '
    {key = $1 OFS $2} 
    NR == FNR {f1[key] = $3; f2[key] = $4; next} 
    !(key in f1) {print $1, $2, 0, 0, $3, $4; next} 
    {print key, f1[key], f2[key], $3, $4; delete f1[key]} 
    END {for (key in f1) print key, f1[key], f2[key], 0, 0}
' file1 file2 | sort
chr loc T1 C1 T2 C2
chr1 100 2 3 1 2
chr1 200 3 4 0 0
chr1 300 0 0 4 1
chr2 100 1 4 7 5
chr2 400 3 1 0 0
chr2 500 0 0 1 9
    
por 16.07.2015 / 23:13