Remplacement des entrées correspondantes dans une colonne d'un fichier par une autre colonne d'un fichier différent

8

J'ai deux fichiers séparés par des tabulations qui se présentent comme suit:

fichier1:

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

fichier2:

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

Je veux faire correspondre la colonne 1 du fichier1 au fichier2 et me remplacer par l'entrée respective de la colonne 2 du fichier 2. La sortie ressemblerait à ceci:

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
BhushanDhamale
la source
Il semble que vous pourriez également être intéressé par notre site partenaire : Bioinformatics .
terdon
Merci pour le lien @terdon!
BhushanDhamale

Réponses:

14

Vous pouvez le faire très facilement avec 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

Ou, puisque cela ressemble à un fichier séparé par des tabulations:

$ 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

Cela suppose que chaque ID RefSeq ( NC_*) file1possède une entrée correspondante dans file2.

Explication

  • NR==FNR: NR est le numéro de ligne actuel, FNR est le numéro de ligne du fichier actuel. Les deux ne seront identiques que pendant la file2lecture du 1er fichier (ici ).
  • a[$1]=$2; next: s'il s'agit du premier fichier (voir ci-dessus), enregistrez le 2ème champ dans un tableau dont la clé est le 1er champ. Ensuite, passez à la nextligne. Cela garantit que le bloc suivant n'est pas exécuté pour le 1er fichier.
  • {$1=a[$1]; print}: maintenant, dans le deuxième fichier, définissez le 1er champ sur la valeur enregistrée dans le tableau apour le 1er champ (donc, la valeur associée de file2) et imprimez la ligne résultante.
terdon
la source
1
NR == FNRne fonctionne pas correctement lorsque le premier fichier est vide. Voir ceci et la réponse associée pour une solution de contournement
iruvar
3
@iruvar rien ne fonctionnera bien si le premier fichier est vide, donc je ne vois pas vraiment pourquoi c'est pertinent. Il s'agit ici de combiner les données des deux fichiers. Si l'un des fichiers est vide, tout l'exercice est inutile.
terdon
désolé j'aurais dû dire dans ce cas particulier file2et n'est pas file1vide. Un comportement sain quand file2est vide est de rapporter le contenu de file1. Le problème avec NR == FNRest que le code qui lui est associé s'exécute sur le contenu de file1when file2is empty
iruvar
3
@iruvar il n'y a aucun comportement sain ici si l'un ou l'autre fichier est vide. C'est ce que je dis :) Il est donc inutile d'essayer de faire face à cette affaire avec élégance. Et, dans tous les cas, lorsque l'un des fichiers est vide ici, rien n'est imprimé. Ce qui semble être l'approche la plus saine, je préfère ne pas obtenir de données plutôt que de mauvaises données.
terdon
17

Pas besoin de awk, en supposant que les fichiers sont triés, vous pouvez utiliser coreutils join:

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

Production:

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

Si vos fichiers ne sont pas triés, vous pouvez soit les trier d'abord ( sort file1 > file1.sorted; sort file2 > file2.sorted) puis utiliser la commande ci-dessus, soit, si votre shell prend en charge la <()construction (bash le fait), vous pouvez faire:

join -o '2.2 1.2 1.3 1.4 1.5' <(sort file1) <(sort file2)
Thor
la source
0

Testé avec la commande ci-dessous et a bien fonctionné

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

production

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
Praveen Kumar BS
la source