Как объединить два файла на основе данных в нескольких столбцах? - PullRequest
1 голос
/ 10 апреля 2020

У меня есть два отдельных файла, каждый из которых содержит разное количество столбцов, которые я хочу объединить на основе данных в нескольких столбцах.

file1

VMNF01000015.1  1769465 1769675 .   .   -   Focub_II5_mimp_1
VMNF01000014.1  3225875 3226081 .   .   +   Focub_II5_mimp_1
VMNF01000014.1  3226046 3226081 .   .   -   Focub_II5_mimp_1
VMNF01000014.1  3585246 3585281 .   .   -   Focub_II5_mimp_1
VMNF01000014.1  3692468 3692503 .   .   -   Focub_II5_mimp_1
VMNF01000014.1  3715380 3715415 .   .   +   Focub_II5_mimp_1
VMNF01000014.1  2872478 2872511 .   .   -   Focub_II5_mimp_1

file2

VMNF01000014.1  3225875-3226081(+)  gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  3226046-3226081(-)  tacacacctgcgaatactttttgcatcccactgta
VMNF01000015.1  1769465-1769675(-)  gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  3692468-3692503(-)  tacagtgggatgcaaaaagtattcgcaggtgt
VMNF01000014.1  3715380-3715415(+)  gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  3585246-3585281(-)  tacagtgggatgcaaaaagtattcgcaggtgt
VMNF01000014.1  2872478-2872511(-)  gtacttcagcctggattcaaacttattgcatcccactgta

Во-первых, я думаю, мне нужно создать еще 2 столбца в file2, разделив числа на "-" и создав новый столбец для "(*)", но я не могу понять, как разделить числа без замены "(-)" тоже. До сих пор я использовал эту команду:

awk '{gsub("-","\t",$2);print;}'

Как только это будет сделано, я хотел бы добавить последний столбец в file2 в file1. Я смог сделать это с помощью следующей команды:

awk 'NR==FNR {a[$1]=$3; next} {print $1,$2,$3,$4,$5,$6,$7,a[$1];}' file2 file1 > file3. 

Однако данные не совпадают. Он сопоставляется на основе записи в столбце 1. Во многих случаях данные в столбце 1 совпадают, поэтому данные в столбце 8 файла3 соответствуют только одной из записей и не соответствуют данным в столбце 2 или 3. в файле1, например,

файл3:

VMNF01000015.1  1769465 1769675 .   .   -   Focub_II5_mimp_1    gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  3225875 3226081 .   .   +   Focub_II5_mimp_1    gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  3226046 3226081 .   .   -   Focub_II5_mimp_1    gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  3585246 3585281 .   .   -   Focub_II5_mimp_1    gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  3692468 3692503 .   .   -   Focub_II5_mimp_1    gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  3715380 3715415 .   .   +   Focub_II5_mimp_1    gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  2872478 2872511 .   .   -   Focub_II5_mimp_1    gtacttcagcctggattcaaacttattgcatcccactgta

Даже если бы мне удалось разделить данные в столбце 2 файла2, у меня все равно была бы та же проблема, что и в данных в столбце 2. то же самое в некоторых случаях. Мне нужен код, который говорит что-то вроде: разделить данные в столбце 2 (см. Ниже);

VMNF01000014.1  3225875    3226081    (+)   gtacttcagcctggattcaaacttattgcatcccactgta

затем:

если $ 1, $ 2, $ 3 в файле1 соответствуют $ 1, $ 2, $ 3 в файле2, выведите $ 1, $ 2, $ 3, $ 4, 5, $ 6, $ 7 из файла1 и добавьте 5 долларов от file2.

Как я могу это сделать? Я знаю, что awk может использовать операторы if, но я не знаю, как их использовать в awk.

Есть совет?

Ответы [ 2 ]

2 голосов
/ 10 апреля 2020
$ awk '
    { key=$1 OFS $2 OFS $3 }
    NR==FNR { map[key]=$NF; next }
    { print $0, map[key] }
' FS='[[:space:](-]+' file2 FS=' ' file1
VMNF01000015.1  1769465 1769675 .   .   -   Focub_II5_mimp_1 gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  3225875 3226081 .   .   +   Focub_II5_mimp_1 gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  3226046 3226081 .   .   -   Focub_II5_mimp_1 tacacacctgcgaatactttttgcatcccactgta
VMNF01000014.1  3585246 3585281 .   .   -   Focub_II5_mimp_1 tacagtgggatgcaaaaagtattcgcaggtgt
VMNF01000014.1  3692468 3692503 .   .   -   Focub_II5_mimp_1 tacagtgggatgcaaaaagtattcgcaggtgt
VMNF01000014.1  3715380 3715415 .   .   +   Focub_II5_mimp_1 gtacttcagcctggattcaaacttattgcatcccactgta
VMNF01000014.1  2872478 2872511 .   .   -   Focub_II5_mimp_1 gtacttcagcctggattcaaacttattgcatcccactgta
2 голосов
/ 10 апреля 2020

Не могли бы вы попробовать следующее.

awk '
FNR==NR{
  split($2,array,"[-(]")
  mainarray[$1,array[1],array[2]]=$NF
  next
}
(($1,$2,$3) in mainarray){
  print $0,mainarray[$1,$2,$3]
}
'  Input_file2  Input_file1

2-е решение: Поскольку OP получает ошибку в вышеприведенном коде, поэтому внесены небольшие изменения в вышеприведенном.

awk '
FNR==NR{
  split($2,array,"[-(]")
  key=$1 OFS array[1] OFS array[2]
  mainarray[key]=$NF
  next
}
{ key = $1 OFS $2 OFS $3 }
(key in mainarray){
  print $0,mainarray[key]
}
'  Input_file2  Input_file1

Объяснение: Добавление подробного пояснения к приведенному выше коду.

awk '                                       ##Starting awk program from here.
FNR==NR{                                    ##Checking condition FNR==NR when  Input_file2 is being read.
  split($2,array,"[-(]")                    ##Splitting 2nd field into an array named array where delimiter is - OR (
  mainarray[$1,array[1],array[2]]=$NF       ##Creating mainarray index of $1,array[1],array[2] and value is current line is last field.
  next                                      ##next will skip all further statements from here.
}
(($1,$2,$3) in mainarray){                  ##Checking condition if $1,$2,$3 of current line is present in mainaarray.
  print $0,mainarray[$1,$2,$3]              ##Printing current line with value of mainarray with index of $1,$2,$3
}
'  Input_file2  Input_file1                 ##Mentioning Input_file names here.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...