Mengganti entri yang cocok dalam satu kolom file dengan kolom lain dari file yang berbeda

8

Saya memiliki dua file tab-terpisah yang terlihat sebagai berikut:

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

Saya ingin mencocokkan kolom 1 dari file1 ke file2 dan menggantikannya dengan entri kolom 2 masing-masing dari file 2. Outputnya akan terlihat seperti ini:

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
sumber
Sepertinya Anda mungkin juga tertarik dengan situs saudara kami: Bioinformatika .
terdon
Terima kasih atas tautannya @terdon!
BhushanDhamale

Jawaban:

14

Anda dapat melakukannya dengan sangat mudah dengan 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

Atau, karena itu terlihat seperti file yang dipisahkan-tab:

$ 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

Ini mengasumsikan bahwa setiap NC_*id RefSeq ( ) di file1memiliki entri yang sesuai di file2.

Penjelasan

  • NR==FNR: NR adalah nomor baris saat ini, FNR adalah nomor baris file saat ini. Keduanya akan identik hanya saat file 1 (di sini, file2) sedang dibaca.
  • a[$1]=$2; next: jika ini adalah file pertama (lihat di atas), simpan bidang ke-2 dalam array yang kuncinya adalah bidang ke-1. Kemudian, lanjutkan ke nextgaris. Ini memastikan blok berikutnya tidak dijalankan untuk file ke-1.
  • {$1=a[$1]; print}: sekarang, di file kedua, setel bidang 1 ke nilai apa pun yang disimpan dalam array auntuk bidang 1 (jadi, nilai terkait dari file2) dan cetak baris yang dihasilkan.
terdon
sumber
1
NR == FNRtidak berfungsi dengan benar saat file pertama kosong. Lihat ini dan jawaban yang terkait untuk solusi
iruvar
3
@iruvar tidak akan bekerja dengan baik jika file pertama kosong, jadi saya tidak benar-benar mengerti mengapa itu relevan. Seluruh poin di sini adalah untuk menggabungkan data dari dua file. Jika salah satu file kosong, seluruh latihan tidak ada gunanya.
terdon
maaf saya seharusnya mengatakan dalam kasus khusus ini file2dan tidak file1kosong. Perilaku waras saat file2kosong adalah melaporkan isi file1. Masalahnya NR == FNRadalah kode yang terkait dengannya dieksekusi pada isi file1saat file2kosong
iruvar
3
@iruvar tidak ada perilaku waras di sini jika salah satu file kosong. Itulah yang saya katakan :) Jadi mencoba menyelesaikannya dengan anggun tidak ada gunanya. Dan, dalam hal apa pun, ketika salah satu file kosong di sini, tidak ada yang dicetak. Yang sebenarnya tampak seperti pendekatan paling sehat, saya lebih suka tidak mendapatkan data daripada data yang salah.
terdon
17

Tidak perlu awk, dengan asumsi file diurutkan, Anda dapat menggunakan coreutils bergabung:

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

Keluaran:

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

Jika file Anda tidak diurutkan, Anda dapat mengurutkannya terlebih dahulu ( sort file1 > file1.sorted; sort file2 > file2.sorted) dan kemudian menggunakan perintah di atas, atau, jika shell Anda mendukung <()konstruk (bash tidak), Anda dapat melakukan:

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

Diuji dengan perintah di bawah dan bekerja dengan baik

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

keluaran

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
sumber