วิธีผสานสองไฟล์ตามการจับคู่ของสองคอลัมน์


33

ฉันชอบ file1:

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

และไฟล์ 2:

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

และต้องการไฟล์ 3 เช่นนั้น:

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

ซึ่งหมายถึงการวางคอลัมน์ที่ 4 ของ file2 ไปที่ file1 ด้วยชื่อของคอลัมน์ที่ 2


1
File2 มีสามคอลัมน์เท่านั้น?
แบร์นฮาร์ด

คำตอบ:


48

สิ่งนี้ควรทำ:

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

สำคัญ : สิ่งนี้ถือว่าไฟล์ของคุณถูกจัดเรียง (ตามตัวอย่าง) ตามชื่อ SNP หากไม่ใช่ให้เรียงลำดับก่อน:

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

เอาท์พุท:

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

คำอธิบาย (จากinfo join):

`join 'เขียนไปยังเอาต์พุตมาตรฐานบรรทัดสำหรับแต่ละคู่ของบรรทัดอินพุตที่มีฟิลด์การรวมที่เหมือนกัน

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

ดังนั้นคำสั่งดังกล่าวจะรวมไฟล์ในฟิลด์ที่สองและพิมพ์ฟิลด์ที่ 1, 2 และ 3 ของไฟล์หนึ่งแล้วตามด้วยฟิลด์ที่ 3 ของ file2


16

คุณสามารถใช้awk:

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

เอาท์พุท:

$ 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

คำอธิบาย:

Walk through file2( NR==FNRเป็นจริงสำหรับอาร์กิวเมนต์ไฟล์แรกเท่านั้น) บันทึกคอลัมน์ที่ 3 ในกัญชาอาร์เรย์โดยใช้คอลัมน์ 2 h[$2] = $3เป็นสำคัญ: จากนั้นเดินผ่านfile1และเอาท์พุททั้งสามคอลัมน์$1,$2,$3, h[$2]ท้ายคอลัมน์บันทึกที่สอดคล้องกันจากกัญชาอาร์เรย์


ขอบคุณมาก. แค่สงสัยว่า 'h [$ 2] = $ 3' หมายถึงอะไร ที่จริงฉันต้องตรงกับ file1 $ 2 == file2 $ 2 ในกรณีที่ซับซ้อนของฉัน (ที่ไม่จำเป็นในลำดับเดียวกัน)
Dadong Zhang

1
h[$2] = $3คือการมอบหมายแฮช มันบันทึก$3เป็นค่าและ$2เป็นกุญแจสำคัญ ตัวอย่าง: h["name"] = "Dadong". ตอนนี้เอาท์พุทprint h["name"] Dadongมันทำสิ่งที่คุณต้องการมันตรงกับคอลัมน์ที่สองจากทั้งสองไฟล์
grebneke

6

หากคุณไม่ต้องการสั่งซื้อใด ๆ จะมีวิธีแก้ปัญหาง่ายๆ

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

สิ่งนี้อนุมานว่าแถวทั้งหมดมีสามรายการและคอลัมน์ 1 และ 2 ของทั้งสองไฟล์เหมือนกัน (เช่นในข้อมูลตัวอย่างของคุณ)


1
+1 สำหรับการใช้งานที่ยอดเยี่ยมของpaste
grebneke

1
@grebneke และ Bernhard เนื่องจากคุณดูเหมือนจะเป็นแฟนของpasteคุณสามารถหาวิธีที่จะตอบคำถามนี้ด้วย coreutils หรือไม่?
terdon

@terdon - ความอ่อนน้อมถ่อมตน: unix.stackexchange.com/a/113909/32165
grebneke

1
@terdon ผมแนะนำให้ไปพิจารณาโปรแกรมที่ outputting s นี้ ***
เบอร์นาร์ด

ไม่มีอะไรผิดปกติกับรูปแบบแท็บไฟล์ที่แยกออกจากกันอย่างสมบูรณ์ ไม่ว่าในกรณีใด ๆ ด้วยข้อมูลประเภทนี้คุณมักจะไม่มีตัวเลือกในการจัดรูปแบบมันมาจากโปรแกรมอื่น
terdon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.