Як об’єднати два файли на основі відповідності двох стовпців?


33

У мене є файл1 лайк:

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-е поле файлу2.


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

Пояснення:

Пройдіться 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 Я б радив переглянути програму, яка виводить цю програму ***
Бернхард

Нічого поганого у форматі, ідеально пристойні файли, розділені на вкладку. У будь-якому випадку, з таким типом даних у вас зазвичай немає вибору щодо формату, він виходить з іншої програми.
тердон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.