Como mesclar dois arquivos com base na correspondência de duas colunas?

27

Eu tenho gostos de arquivo1:

0   AFFX-SNP-000541  NA
0   AFFX-SNP-002255  NA
1   rs12103          0.6401
1   rs12103_1247494  0.696
1   rs12142199       0.7672

E um arquivo2:

0   AFFX-SNP-000541   1
0   AFFX-SNP-002255   1
1   rs12103           0.5596
1   rs12103_1247494   0.5581
1   rs12142199        0.4931

E gostaria que um arquivo3 assim:

0   AFFX-SNP-000541     NA       1
0   AFFX-SNP-002255     NA       1
1   rs12103             0.6401   0.5596
1   rs12103_1247494     0.696    0.5581
1   rs12142199          0.7672   0.4931

O que significa colocar a quarta coluna do arquivo2 no arquivo1 pelo nome da segunda coluna.

    
por Dadong Zhang 06.02.2014 / 21:03

3 respostas

44

Isso deve ser feito:

join -j 2 -o 1.1,1.2,1.3,2.3 file1 file2

Importante : isso pressupõe que seus arquivos estejam classificados (como no seu exemplo) de acordo com o nome do SNP. Se não estiverem, classifique-os primeiro:

join -j 2 -o 1.1,1.2,1.3,2.3 <(sort -k2 file1) <(sort -k2 file2)

Saída:

0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.6401 0.5596
1 rs12103_1247494 0.696 0.5581
1 rs12142199 0.7672 0.4931

Explicação (de info join ):

'join' writes to standard output a line for each pair of input lines that have identical join fields.

'-1 FIELD'
     Join on field FIELD (a positive integer) of file 1.

'-2 FIELD'
     Join on field FIELD (a positive integer) of file 2.

'-j FIELD'
     Equivalent to '-1 FIELD -2 FIELD'.

'-o FIELD-LIST'

 Otherwise, construct each output line according to the format in
 FIELD-LIST.  Each element in FIELD-LIST is either the single
 character '0' or has the form M.N where the file number, M, is '1'
 or '2' and N is a positive field number.

Assim, o comando acima junta os arquivos no segundo campo e imprime o primeiro, segundo e terceiro campo do arquivo um, seguido pelo terceiro campo do arquivo2.

    
por 06.02.2014 / 21:32
15

Você pode usar awk :

$ awk 'NR==FNR {h[$2] = $3; next} {print $1,$2,$3,h[$2]}' file2 file1 > file3

saída:

$ cat file3
0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.6401 0.5596
1 rs12103_1247494 0.696 0.5581
1 rs12142199 0.7672 0.4931

Explicação:

Percorrer file2 ( NR==FNR é verdadeiro apenas para o primeiro argumento de arquivo). Salve a coluna 3 no array de hash usando a coluna 2 como chave: h[$2] = $3 . Em seguida, percorra file1 e imprima todas as três colunas $1,$2,$3 , anexando a coluna salva correspondente de hash-array h[$2] .

    
por 06.02.2014 / 21:30
6

Se você não precisar de nenhum pedido, então uma solução simples seria

paste file{1,2} | awk '{print $1,$2,$3,$6}' > file3

Isso pressupõe que todas as linhas têm três entradas, e as colunas 1 e 2 de ambos os arquivos são as mesmas (como em seus dados de exemplo)

    
por 06.02.2014 / 21:40