Sostituzione di voci corrispondenti in una colonna di un file con un'altra colonna di un altro file


8

Ho due file separati da tab che si presentano come segue:

file1:

NC_008146.1     WP_011558474.1  1155234 1156286 44173
NC_008146.1     WP_011558475.1  1156298 1156807 12
NC_008146.1     WP_011558476.1  1156804 1157820 -3
NC_008705.1     WP_011558474.1  1159543 1160595 42748
NC_008705.1     WP_011558475.1  1160607 1161116 12
NC_008705.1     WP_011558476.1  1161113 1162129 -3
NC_009077.1     WP_011559727.1  2481079 2481633 8
NC_009077.1     WP_011854835.1  1163068 1164120 42559
NC_009077.1     WP_011854836.1  1164127 1164636 7

file2:

NC_008146.1     GCF_000014165.1_ASM1416v1_protein.faa
NC_008705.1     GCF_000015405.1_ASM1540v1_protein.faa
NC_009077.1     GCF_000016005.1_ASM1600v1_protein.faa

Voglio abbinare la colonna 1 di file1 a file2 e sostituirlo con la rispettiva voce di colonna 2 del file 2. L'output sarebbe simile al seguente:

GCF_000014165.1_ASM1416v1_protein.faa     WP_011558474.1  1155234 1156286 44173
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558475.1  1156298 1156807 12
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558476.1  1156804 1157820 -3
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558474.1  1159543 1160595 42748
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558475.1  1160607 1161116 12
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558476.1  1161113 1162129 -3
GCF_000016005.1_ASM1600v1_protein.faa     WP_011559727.1  2481079 2481633 8
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854835.1  1163068 1164120 42559
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854836.1  1164127 1164636 7

Sembra che potresti essere interessato anche al nostro sito gemello : Bioinformatica .
terdon

Grazie per il link @terdon!
BhushanDhamale,

Risposte:


14

Puoi farlo molto facilmente con awk:

$ awk 'NR==FNR{a[$1]=$2; next}{$1=a[$1]; print}' file2 file1
GCF_000014165.1_ASM1416v1_protein.faa WP_011558474.1 1155234 1156286 44173
GCF_000014165.1_ASM1416v1_protein.faa WP_011558475.1 1156298 1156807 12
GCF_000014165.1_ASM1416v1_protein.faa WP_011558476.1 1156804 1157820 -3
GCF_000015405.1_ASM1540v1_protein.faa WP_011558474.1 1159543 1160595 42748
GCF_000015405.1_ASM1540v1_protein.faa WP_011558475.1 1160607 1161116 12
GCF_000015405.1_ASM1540v1_protein.faa WP_011558476.1 1161113 1162129 -3
GCF_000016005.1_ASM1600v1_protein.faa WP_011559727.1 2481079 2481633 8
GCF_000016005.1_ASM1600v1_protein.faa WP_011854835.1 1163068 1164120 42559
GCF_000016005.1_ASM1600v1_protein.faa WP_011854836.1 1164127 1164636 7

Oppure, dal momento che sembra un file separato da tabulazioni:

$ awk -vOFS="\t" 'NR==FNR{a[$1]=$2; next}{$1=a[$1]; print}' file2 file1
GCF_000014165.1_ASM1416v1_protein.faa   WP_011558474.1  1155234 1156286 44173
GCF_000014165.1_ASM1416v1_protein.faa   WP_011558475.1  1156298 1156807 12
GCF_000014165.1_ASM1416v1_protein.faa   WP_011558476.1  1156804 1157820 -3
GCF_000015405.1_ASM1540v1_protein.faa   WP_011558474.1  1159543 1160595 42748
GCF_000015405.1_ASM1540v1_protein.faa   WP_011558475.1  1160607 1161116 12
GCF_000015405.1_ASM1540v1_protein.faa   WP_011558476.1  1161113 1162129 -3
GCF_000016005.1_ASM1600v1_protein.faa   WP_011559727.1  2481079 2481633 8
GCF_000016005.1_ASM1600v1_protein.faa   WP_011854835.1  1163068 1164120 42559
GCF_000016005.1_ASM1600v1_protein.faa   WP_011854836.1  1164127 1164636 7

Ciò presuppone che ogni ID RefSeq ( NC_*) in file1abbia una voce corrispondente in file2.

Spiegazione

  • NR==FNR: NR è il numero di riga corrente, FNR è il numero di riga del file corrente. I due saranno identici solo durante la file2lettura del primo file (qui, ).
  • a[$1]=$2; next: se questo è il primo file (vedi sopra), salva il secondo campo in un array la cui chiave è il primo campo. Quindi, passa alla nextlinea. Ciò garantisce che il blocco successivo non venga eseguito per il 1o file.
  • {$1=a[$1]; print}: ora, nel secondo file, imposta il 1 ° campo su qualsiasi valore salvato nell'array aper il 1 ° campo (quindi, il valore associato da file2) e stampa la riga risultante.

1
NR == FNRnon funziona correttamente quando il primo file è vuoto. Vedi questo e la risposta associata per una soluzione alternativa
iruvar

3
@iruvar niente funzionerà bene se il primo file è vuoto, quindi non vedo perché sia ​​rilevante. L'intero punto qui è combinare i dati dei due file. Se uno dei file è vuoto, l'intero esercizio è inutile.
terdon

scusate avrei dovuto dirlo in questo caso particolare file2e non file1è vuoto. Comportamento sano quando file2è vuoto è quello di segnalare il contenuto di file1. Il problema NR == FNRè che il codice ad esso associato viene eseguito sul contenuto di file1quando file2è vuoto
iruvar

3
@iruvar non c'è alcun comportamento sano qui se uno dei file è vuoto. Questo è quello che sto dicendo :) Quindi cercare di far fronte a quel caso con grazia non ha senso. E, in ogni caso, quando uno dei file è vuoto qui, non viene stampato nulla. Che in realtà sembra l'approccio più sano, preferirei non avere dati che dati errati.
terdon

17

Non è necessario awk, supponendo che i file siano ordinati, è possibile utilizzare coreutils join:

join -o '2.2 1.2 1.3 1.4 1.5' file1 file2

Produzione:

GCF_000014165.1_ASM1416v1_protein.faa     WP_011558474.1  1155234 1156286 44173
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558475.1  1156298 1156807 12
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558476.1  1156804 1157820 -3
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558474.1  1159543 1160595 42748
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558475.1  1160607 1161116 12
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558476.1  1161113 1162129 -3
GCF_000016005.1_ASM1600v1_protein.faa     WP_011559727.1  2481079 2481633 8
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854835.1  1163068 1164120 42559
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854836.1  1164127 1164636 7

Se i tuoi file non sono, ordinati, puoi prima ordinarli ( sort file1 > file1.sorted; sort file2 > file2.sorted) e poi usare il comando sopra, oppure, se la tua shell supporta il <()costrutto (bash lo fa), puoi fare:

join -o '2.2 1.2 1.3 1.4 1.5' <(sort file1) <(sort file2)

0

Testato con il comando seguente e ha funzionato bene

for i in `awk '{print $1}' f2`; do k=`awk -v i="$i" '$1==i {print $2}' f2`;sed  "/$i/s/$i/$k/g" f1 >f3;done

produzione

for i in `awk '{print $1}' f2`; do k=`awk -v i="$i" '$1==i {print $2}' f2`;sed  "/$i/s/$i/$k/g" f1 >f3;done


GCF_000014165.1_ASM1416v1_protein.faa     WP_011558474.1  1155234 1156286 44173
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558475.1  1156298 1156807 12
GCF_000014165.1_ASM1416v1_protein.faa     WP_011558476.1  1156804 1157820 -3
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558474.1  1159543 1160595 42748
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558475.1  1160607 1161116 12
GCF_000015405.1_ASM1540v1_protein.faa     WP_011558476.1  1161113 1162129 -3
GCF_000016005.1_ASM1600v1_protein.faa     WP_011559727.1  2481079 2481633 8
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854835.1  1163068 1164120 42559
GCF_000016005.1_ASM1600v1_protein.faa     WP_011854836.1  1164127 1164636 7
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.