Come unire due file in base alla corrispondenza di due colonne?


33

Ho file1 "Mi piace":

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

E un file2:

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

E vorrebbe un file3 tale che:

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

Il che significa mettere la quarta colonna di file2 in file1 con il nome della seconda colonna.


1
File2 ha solo tre colonne?
Bernhard,

Risposte:


48

Questo dovrebbe farlo:

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

Importante : questo presuppone che i file siano ordinati (come nell'esempio) in base al nome SNP. Se non lo sono, ordinali prima:

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

Produzione:

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

Spiegazione (da info join):

`join 'scrive nell'output standard una riga per ogni coppia di righe di input che hanno campi di join identici.

`-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.

Quindi, il comando sopra unisce i file sul secondo campo e stampa il 1 °, 2 ° e 3 ° campo del file uno, seguito dal 3 ° campo del file2.


16

Puoi usare awk:

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

produzione:

$ 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

Spiegazione:

Walk through file2( NR==FNRè vero solo per il primo argomento del file). Salva colonna 3 in hash-array usando colonna 2 come la chiave: h[$2] = $3. Quindi attraversa file1e genera tutte e tre le colonne $1,$2,$3, aggiungendo la colonna salvata corrispondente dall'hash-array h[$2].


Molte grazie. Mi chiedo, cosa significa "h [$ 2] = $ 3"? In realtà ho bisogno di abbinare esattamente il file1 $ 2 == file2 $ 2 nei miei casi complessi (che non sono necessari nello stesso ordine).
Dadong Zhang,

1
h[$2] = $3è un compito hash. Salva $3come valore e $2come chiave. Esempio: h["name"] = "Dadong". Ora, print h["name"]uscite Dadong. Fa quello che vuoi, corrisponde esattamente alla seconda colonna di entrambi i file.
Grebneke,

6

Se non hai bisogno di alcun ordine, sarebbe una soluzione semplice

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

Ciò presume che tutte le righe abbiano tre voci e che le colonne 1 e 2 di entrambi i file siano uguali (come nei dati di esempio)


1
+1 per un ottimo uso dipaste
grebneke,

1
@grebneke e Bernhard, dal momento che sembri fan di pasteriesci a trovare un modo per rispondere a questo con coreutils?
terdon

@terdon - un umile tentativo: unix.stackexchange.com/a/113909/32165
grebneke

1
@terdon Consiglierei di riconsiderare il programma che sta producendo questo s ***
Bernhard

Niente di sbagliato nel formato, file separati da tab perfettamente decenti. In ogni caso, con questo tipo di dati di solito non hai scelta sul formato, viene fuori da un altro programma.
terdon
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.