Làm cách nào để hợp nhất hai tệp dựa trên sự khớp của hai cột?


33

Tôi có file1 lượt thích:

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

Và một tập tin2:

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

Và muốn một file3 sao cho:

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

Có nghĩa là đặt cột thứ 4 của tệp2 vào tệp1 theo tên của cột thứ 2.


1
File2 chỉ có ba cột?
Bernhard

Câu trả lời:


48

Điều này nên làm điều đó:

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

Quan trọng : điều này giả sử các tệp của bạn được sắp xếp (như trong ví dụ của bạn) theo tên SNP. Nếu không, hãy sắp xếp chúng trước:

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

Đầu ra:

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

Giải thích (từ info join):

`tham gia 'ghi vào đầu ra tiêu chuẩn một dòng cho mỗi cặp dòng đầu vào có các trường tham gia giống hệt nhau.

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

Vì vậy, lệnh trên kết hợp các tệp trên trường thứ hai và in trường thứ 1, 2 và 3 của tệp một, tiếp theo là trường thứ 3 của tệp2.


16

Bạn có thể sử dụng awk:

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

đầu ra:

$ 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

Giải trình:

Đi qua file2( NR==FNRchỉ đúng với đối số tệp đầu tiên). Lưu cột 3 trong mảng băm bằng cách sử dụng cột 2 làm khóa : h[$2] = $3. Sau đó đi qua file1và xuất tất cả ba cột $1,$2,$3, nối thêm cột đã lưu tương ứng từ mảng băm h[$2].


Cảm ơn rất nhiều. Chỉ cần tự hỏi, 'h [$ 2] = $ 3' nghĩa là gì? Trên thực tế tôi cần khớp chính xác tệp1 $ 2 == file2 $ 2 trong các trường hợp phức tạp của tôi (không cần thiết theo cùng một thứ tự).
Dadong Zhang

1
h[$2] = $3là một bài tập băm. Nó lưu $3dưới dạng giá trị và $2là chìa khóa. Ví dụ : h["name"] = "Dadong". Bây giờ, print h["name"]đầu ra Dadong. Nó làm những gì bạn muốn, nó khớp chính xác với cột thứ hai từ cả hai tệp.
grebneke

6

Nếu bạn không cần bất kỳ đơn đặt hàng nào, thì một giải pháp đơn giản sẽ là

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

Điều này giả định rằng tất cả các hàng có ba mục nhập và cột 1 và 2 của cả hai tệp đều giống nhau (như trong dữ liệu ví dụ của bạn)


1
+1 để sử dụng tuyệt vờipaste
grebneke 6/214

1
@grebneke và Bernhard, vì dường như bạn là người hâm mộ, pastebạn có thể tìm ra cách để trả lời điều này với coreutils không?
terdon

@terdon - một nỗ lực khiêm tốn: unix.stackexchange.com/a/113909/32165
grebneke

1
@terdon Tôi khuyên bạn nên xem xét lại chương trình đang xuất ra s *** này
Bernhard

Không có gì sai với định dạng, các tệp hoàn toàn tách biệt hoàn toàn. Trong mọi trường hợp, với loại dữ liệu này, bạn thường không có lựa chọn nào về định dạng, nó xuất phát từ một chương trình khác.
terdon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.