замена части строки значением из другого столбца postgresql - PullRequest
0 голосов
/ 14 июля 2020

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

Amino acid change
------------------------ 
NP_006209.2:p.<b>Thr</b>1025<b>Ala</b>
NP_203524.1:p.<b>Gly</b>12<b>Asp</b>  
NP_000537.3:p.<b>Arg</b>273<b>Cys</b> 
NP_004324.2:p.<b>Val</b>600<b>Glu</b> 
NP_000537.3:p.<b>Ser</b>215<b>Ile</b>

В другой таблице у меня есть трехбуквенный код и однобуквенный код следующие аминокислоты:

three_letters|one_letters
-------------|-----------
Ala          |A          
Arg          |R          
Asn          |N          
Asp          |D             
...
Val          |V          
Asx          |B          
Glx          |Z          
Ter          |*          

Мне нужен новый столбец в моей таблице мутаций с аминокислотами в виде однобуквенного кода, как показано ниже:

new column
----------- 
p.<b>T</b>1025<b>A</b>  
p.<b>G</b>12<b>D</b>    
p.<b>R</b>273<b>C</b>   
p.<b>V</b>600<b>E</b>   
p.<b>S</b>215<b>I</b>

Ответы [ 3 ]

0 голосов
/ 14 июля 2020

Альтернативой решению, предложенному @Mike Organek, является создание короткой функции для выполнения этого преобразования за вас.

Образец данных:

CREATE TEMPORARY TABLE map (three_letters text, one_letters text);
INSERT INTO map 
VALUES ('Val','V'),('Glu','E'),('Thr','T'),('Ala','A');

Функция:

CREATE OR REPLACE FUNCTION change_amino_acid(text)
RETURNS TEXT AS $BODY$
DECLARE i RECORD; acid TEXT;
BEGIN
acid := trim((string_to_array($1, ':p.'))[2]);
FOR i IN SELECT * FROM map 
  WHERE three_letters = ANY(regexp_split_to_array(acid, '\d+'))
LOOP
  acid := replace(acid,i.three_letters,i.one_letters);
END LOOP;
RETURN 'p.'||acid;
END; $BODY$ LANGUAGE plpgsql;

Как вызвать функцию:

SELECT 
  change_amino_acid('NP_006209.2:p.Thr1025Ala'),
  change_amino_acid('NP_004324.2:p.Val600Glu');

 change_amino_acid | change_amino_acid 
-------------------+-------------------
 p.T1025A          | p.V600E

После этого все, что вам нужно сделать, это UPDATE вашу таблицу с помощью функции

UPDATE my_table 
SET newcolum = change_amino_acid(long_amino_acid);
0 голосов
/ 14 июля 2020

Ваша строка имеет очень специфический формат. Префикс имеет фиксированную длину. Затем следуют три символа, число (предположительно, позиция), а затем еще три символа.

Если это всегда так, вам не нужно какое-либо настоящее сложное оборудование для замены. Вы можете просто использовать строковые операции:

with replacements as (
      select 'Thr' as three_letters, 'T' as one_letter union all
      select 'Ala' as three_letters, 'A' as one_letter
     ) 
select v.*, 
       left(mutation, 14) || r1.one_letter || replace(substr(mutation, 18), r2.three_letters, r2.one_letter)
from (values ('NP_006209.2:p.Thr1025Ala')) v(mutation) left join
     replacements r1
     on r1.three_letters = substr(mutation, 15, 3) left join
     replacements r2
     on r2.three_letters = right(mutation, 3);

Я бы действительно рекомендовал вам изменить структуру данных, чтобы все значения не были закодированы в одной строке. Поместите результаты в несколько столбцов:

  • name
  • from_amino_acid
  • to_amino_acid
  • position

На самом деле, я не знаю, что происходит до :, и важен ли p.. Вы также можете разделить это на несколько столбцов. Вы можете использовать logi c, чтобы разделить строку:

select split_part(mutation, ':', 1) as name,
       substring(split_part(mutation, ':', 2), 3, 3) as from_amino_acid,
       (regexp_matches(split_part(mutation, ':', 2), '[0-9]+'))[1] as position,
       right(mutation, 3) as to_amino_acid
from (values ('NP_006209.2:p.Thr1025Ala')) v(mutation);

Это упростит ваш SQL и, возможно, ваш анализ.

0 голосов
/ 14 июля 2020

Вы можете решить эту проблему с помощью регулярного выражения, если код изменения всегда состоит из трех букв, за которыми следуют одна или несколько цифр, за которыми следуют три буквы.

regexp_match(change, 'p.(\D{3})(\d+)(\D{3})')

Это возвращает массив, который можно использовать для присоединитесь к вашей таблице поиска и затем восстановите сокращенный код.

with split as (
  select *, 
         regexp_match(change, 'p.(\D{3})(\d+)(\D{3})') as parts
    from changes
)
select s.*, 
       concat('p.', 
              coalesce(x1.one_letters, '?'), 
              parts[2], 
              coalesce(x2.one_letters, '?') 
       ) as encoded_change
  from split s
  left join xlate x1 on x1.three_letters = s.parts[1]
  left join xlate x2 on x2.three_letters = s.parts[3];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...