[英]replacing part of a string with value from another column postgresql
我有一個表格,其中有一列中的突變信息是三個字母代碼中的氨基酸變化,如下所示:
Amino acid change ------------------------ NP_006209.2:p.Thr1025Ala NP_203524.1:p.Gly12Asp NP_000537.3:p.Arg273Cys NP_004324.2:p.Val600Glu NP_000537.3:p.Ser215Ile
在另一張表中,我有氨基酸的三個字母代碼和一個字母代碼如下:
three_letters|one_letters
-------------|-----------
Ala |A
Arg |R
Asn |N
Asp |D
...
Val |V
Asx |B
Glx |Z
Ter |*
我需要在我的突變表中添加一個新列,其中一個字母代碼中的氨基酸如下:
new column ----------- p.T1025A p.G12D p.R273C p.V600E p.S215I
您可以使用正則表達式解決此問題,只要更改代碼始終是三個字母后跟一個或多個數字后跟三個字母。
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];
@Mike Organek 提出的解決方案的替代方法是創建一個簡短的 function 來為您進行此轉換。
數據樣本:
CREATE TEMPORARY TABLE map (three_letters text, one_letters text);
INSERT INTO map
VALUES ('Val','V'),('Glu','E'),('Thr','T'),('Ala','A');
Function:
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;
如何調用 function:
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
之后,您需要做的就是使用 function UPDATE
您的表
UPDATE my_table
SET newcolum = change_amino_acid(long_amino_acid);
您的字符串采用非常特殊的格式。 前綴看起來像一個固定長度。 然后是三個字符,一個數字(可能是一個位置),然后是另外三個字符。
如果情況總是如此,則您不需要任何真正復雜的機器來進行更換。 您可以只使用字符串操作:
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.
很重要。 您可能還希望將其拆分為不止一列。 您可以使用這樣的邏輯來拆分字符串:
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 以及您的分析。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.