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