Используйте извлечение и/или разделение, чтобы изолировать переменную строку от фрейма данных

Я просмотрел следующие страницы по использованию регулярного выражения для изоляции строки:

Регулярное выражение для извлечения текста между квадратными скобками

Что такое группа без захвата? Что делает (?:)?

Разделить столбец строки фрейма данных на несколько столбцов

У меня есть кадр данных, который содержит идентификаторы белка/гена, и в некоторых случаях есть две или более таких строк (разделенных запятой) из-за нескольких совпадений из списка. В этом случае первая строка является самым сильным совпадением, и я не обязательно заинтересован в сохранении остальных. Они представляют собой несколько совпадений из предполагаемых доказательств, и когда их нельзя легко различить, все совпадения помещаются в столбец. В этом случае меня интересует только сохранение первого, потому что группа, вероятно, будет иметь тот же тип аннотации (например, тип белка, онтологию гена, аналогичную функцию и т. д.). Если я разделю несколько записей на несколько строк, то может показаться, что У меня есть доказательства того, что они существуют в моем наборе данных, но на эмпирическом уровне их нет.

Мой фрейм данных:

                protein
1 sp|P50213|IDH3A_HUMAN
2  sp|Q9BZ95|NSD3_HUMAN
3  sp|Q92616|GCN1_HUMAN
4 sp|Q9NSY1|BMP2K_HUMAN
5  sp|O75643|U520_HUMAN
6 sp|O15357|SHIP2_HUMAN
523 sp|P10599|THIO_HUMAN,sp|THIO_HUMAN|
524 sp|Q96KB5|TOPK_HUMAN
525 sp|P12277|KCRB_HUMAN,sp|P17540|KCRS_HUMAN,sp|P12532|KCRU_HUMAN
526 sp|O00299|CLIC1_HUMAN
527 sp|P25940|CO5A3_HUMAN

Вывод, который я пытаюсь создать:

uniprot gene
P50213 IDH3A
Q9BZ95 NSD3
Q92616 GCN1
P12277 KCRB

Я пытаюсь использовать функции extract и separate для этого:

extract(df, protein, into = c("uniprot", "gene"), regex = c("sp|(.*?)|"," 
(.*?)_"), remove = FALSE)

приводит к:

Error: is_string(regex) is not TRUE

пытаясь separate хотя бы разбить их на несколько шагов:

separate(df, protein, into = c("uniprot", "gene"), sep = "|", remove = 
FALSE)

приводит к:

Warning message:
Expected 2 pieces. Additional pieces discarded in 528 rows [1, 2, 3, 4, 5, 
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...]. 
                protein uniprot gene
1 sp|P50213|IDH3A_HUMAN            s
2  sp|Q9BZ95|NSD3_HUMAN            s
3  sp|Q92616|GCN1_HUMAN            s
4 sp|Q9NSY1|BMP2K_HUMAN            s
5  sp|O75643|U520_HUMAN            s
6 sp|O15357|SHIP2_HUMAN            s

Каков наилучший способ использования регулярного выражения в этом сценарии и extract или separate лучший способ сделать это? Любое предложение будет принято с благодарностью. Спасибо!

Обновление на основе отзывов:

df <- structure(list(protein = c("sp|P50213|IDH3A_HUMAN",  "sp|Q9BZ95|NSD3_HUMAN", 
                             "sp|Q92616|GCN1_HUMAN", "sp|Q9NSY1|BMP2K_HUMAN", "sp|O75643|U520_HUMAN", 
                             "sp|O15357|SHIP2_HUMAN", "sp|P10599|THIO_HUMAN,sp|THIO_HUMAN|", 
                             "sp|Q96KB5|TOPK_HUMAN",   "sp|P12277|KCRB_HUMAN,sp|P17540|KCRS_HUMAN,sp|P12532|KCRU_HUMAN", 
                             "sp|O00299|CLIC1_HUMAN")), class = "data.frame", row.names = c("1", 
                                                                                            "2", "3", "4", "5", "6", "523", "524", "525", "526"))
df1 <- separate(df, protein, into = "protein", sep = ",") 
#i'm only interested in the first match, because science

df2 <- extract(df1, protein, into = c("uniprot", "gene"), regex = "sp\\| 
([^|]+)\\|([^_]+)", remove = FALSE) 
#create new columns with uniprot code and gene id, no _HUMAN

#df2
#                 protein uniprot  gene
#1   sp|P50213|IDH3A_HUMAN  P50213 IDH3A
#2    sp|Q9BZ95|NSD3_HUMAN  Q9BZ95  NSD3
#3    sp|Q92616|GCN1_HUMAN  Q92616  GCN1
#4   sp|Q9NSY1|BMP2K_HUMAN  Q9NSY1 BMP2K
#5    sp|O75643|U520_HUMAN  O75643  U520
#6   sp|O15357|SHIP2_HUMAN  O15357 SHIP2
#523  sp|P10599|THIO_HUMAN  P10599  THIO
#524  sp|Q96KB5|TOPK_HUMAN  Q96KB5  TOPK
#525  sp|P12277|KCRB_HUMAN  P12277  KCRB
#526 sp|O00299|CLIC1_HUMAN  O00299 CLIC1

#and the answer using %>% pipes (this is what I aspire to)
df_filtered <- df %>%
separate(protein, into = "protein", sep = ",") %>%
extract(protein, into = c("uniprot", "gene"), regex = "sp\\|([^|]+)\\|([^_]+)") %>%
select(uniprot, gene)

#df_filtered
#    uniprot  gene
#1    P50213 IDH3A
#2    Q9BZ95  NSD3
#3    Q92616  GCN1
#4    Q9NSY1 BMP2K
#5    O75643  U520
#6    O15357 SHIP2
#523  P10599  THIO
#524  Q96KB5  TOPK
#525  P12277  KCRB
#526  O00299 CLIC1

person Adam Rabalski    schedule 05.09.2018    source источник
comment
Как насчет строк 523 и 525? Они выглядят как несколько объединенных строк, как вы хотите, чтобы они были разделены?   -  person acylam    schedule 05.09.2018
comment
Они представляют собой несколько совпадений из предполагаемых свидетельств, и когда их нельзя легко различить, все совпадения помещаются в столбец. В этом случае меня интересует только сохранение первого, потому что группа, вероятно, будет иметь тот же тип аннотации (например, тип белка, онтологию гена, аналогичную функцию и т. д.). Если я разделю несколько записей на несколько строк, то может показаться, что У меня есть доказательства того, что они существуют в моем наборе данных, но на эмпирическом уровне их нет.   -  person Adam Rabalski    schedule 05.09.2018
comment
Вы должны добавить этот комментарий к своему вопросу и обновить желаемый результат, чтобы отразить это   -  person acylam    schedule 05.09.2018


Ответы (1)


Мы можем зафиксировать шаблон как группу ((...)) в extract. Здесь мы сопоставляем sp в начале (^) строки, за которой следует | (метасимвол - экранированный \\), за которым следует один или несколько символов, отличных от |, захваченных как группа, за которыми следует |, и второй набор захваченных символов

library(tidyverse)
extract(df, protein, into = c("uniprot", "gene"), 
     regex = "^sp\\|([^|]+)\\|([^|]+).*")

Если есть несколько экземпляров «sp», разделите строки на длинный формат с помощью separate_rows, а затем используйте extract

df %>%
   separate_rows(protein, sep=",") %>%
   extract(protein, into = c("uniprot", "gene"), 
    "^sp\\|([^|]+)\\|([^|]*).*")

Есть один случай, когда есть только два набора слов. Чтобы заставить его работать

df %>%
  separate_rows(protein, sep=",") %>% 
  extract(protein, into = "gene", "([^|]*HUMAN)", remove = FALSE) %>% 
  mutate(uniprot = str_extract(protein, "(?<=sp\\|)[^_]+(?=\\|)")) %>%
  select(uniprot, gene)
#   uniprot        gene
#1   P50213 IDH3A_HUMAN
#2   Q9BZ95  NSD3_HUMAN
#3   Q92616  GCN1_HUMAN
#4   Q9NSY1 BMP2K_HUMAN
#5   O75643  U520_HUMAN
#6   O15357 SHIP2_HUMAN
#7   P10599  THIO_HUMAN
#8     <NA>  THIO_HUMAN
#9   Q96KB5  TOPK_HUMAN
#10  P12277  KCRB_HUMAN
#11  P17540  KCRS_HUMAN
#12  P12532  KCRU_HUMAN
#13  O00299 CLIC1_HUMAN

данные

df <- structure(list(protein = c("sp|P50213|IDH3A_HUMAN",  "sp|Q9BZ95|NSD3_HUMAN", 
   "sp|Q92616|GCN1_HUMAN", "sp|Q9NSY1|BMP2K_HUMAN", "sp|O75643|U520_HUMAN", 
  "sp|O15357|SHIP2_HUMAN", "sp|P10599|THIO_HUMAN,sp|THIO_HUMAN|", 
  "sp|Q96KB5|TOPK_HUMAN",   "sp|P12277|KCRB_HUMAN,sp|P17540|KCRS_HUMAN,sp|P12532|KCRU_HUMAN", 
  "sp|O00299|CLIC1_HUMAN")), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "523", "524", "525", "526"))
person akrun    schedule 05.09.2018
comment
прямо сейчас функция извлечения изолирует IDH3A_HUMAN, что, если я просто хочу IDH3A? Я пробовал ^sp\\|C[^|]+)\\|([^|]+)\\_, так как я хочу, чтобы все приводило к _, но я получаю сообщение об ошибке, говорящее Incorrectly nested parentheses in regexp pattern. (U_REGEX_MISMATCHED_PAREN) то же самое предупреждение, когда я использую ^sp\\|C[^|]+)\\|([^_HUMAN]+), пытаясь сказать, что все соответствует после |, но _HUMAN - person Adam Rabalski; 05.09.2018
comment
@AdamRabalski Вы можете проверить последний кусок кода - person akrun; 05.09.2018
comment
ОК, я думаю, я понял это так: sp\\|([^|]+)\\|([^_]+), где сказано, что нужно брать все, кроме _, верно? Означает ли предполагаемая функция [^_]+ все, кроме _, и на этом останавливаетесь? Мой вывод не включает HUMAN, поэтому я и спрашиваю. Скоро обновлю свой пост своим ответом. - person Adam Rabalski; 05.09.2018
comment
@AdamRabalski Это подразумевает sp, за которым следует | (метасимвол - экранированный \`), followed by one or more character that are not a |` ([^|]+)`, захваченный как группа, за которой следует |, и вторая захваченная группа символов, которые не являются [ - person akrun; 06.09.2018