Совпадение части шаблона со строкой - PullRequest
0 голосов
/ 16 октября 2018

У меня есть два кадра данных, и я хочу сделать сопоставление и объединить.Первоначально я использовал inner_join и coalesce, но понял, что совпадающая часть не соответствует должным образом.

Я нашел пример, который, кажется, был в правильном направлении Как объединить два фрейма данных на основе частичной строкисовпадать с R? .В одном ответе предлагалось использовать этот код:

idx2 <- sapply(df_mouse_human$Protein.IDs, grep, df_mouse$Protein.IDs) idx1 <- sapply(seq_along(idx2), function(i) rep(i, length(idx2[[i]]))) merged <- cbind(df_mouse_human[unlist(idx1),,drop=F], df_mouse[unlist(idx2),,drop=F])

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

dput(droplevels(df_mouse))
structure(list(Protein.IDs = c("Q8CBM2;A2AL85;Q8BSY0", "A2AMH3;A2AMH5;A2AMH4;Q6X893;Q6X893-2;A2AMH8", 
"A2AMW0;P47757-2;A2AMV7;P47757;F6QJN8;F6YHZ8;F7CAZ6", "Q3U8S1;A2APM5;A2APM3;A2APM4;E9QKM8;Q80X37;A2APM1;A2APM2;P15379-2;P15379-3;P15379-6;P15379-11;P15379-5;P15379-10;P15379-9;P15379-4;P15379-8;P15379-7;P15379;P15379-12;P15379-13", 
"A2ASS6;E9Q8N1;E9Q8K5;A2ASS6-2;A2AT70;F7CR78", "A2AUR7;Q9D031;Q01730"
), Replicate = c(2L, 2L, 2L, 2L, 2L, 2L), Ratio.H.L.normalized.01 = c(NaN, 
NaN, NaN, NaN, NaN, NaN), Ratio.H.L.normalized.02 = c(NaN, NaN, 
NaN, NaN, NaN, NaN), Ratio.H.L.normalized.03 = c(NaN, NaN, NaN, 
NaN, NaN, NaN)), .Names = c("Protein.IDs", "Replicate", "Ratio.H.L.normalized.01", 
"Ratio.H.L.normalized.02", "Ratio.H.L.normalized.03"), row.names = 12:17, class = "data.frame")

dput(droplevels(df_mouse_human))
structure(list(Human = c("Q8WZ42", "Q8NF91", "Q9UPN3", "Q96RW7", 
"Q8WXG9", "P20929", "Q5T4S7", "O14686", "Q2LD37", "Q92736"), 
    Protein.IDs = c("A2ASS6", "Q6ZWR6", "Q9QXZ0", "D3YXG0", "Q8VHN7", 
    "E9Q1W3", "A2AN08", "Q6PDK2", "A2AAE1", "E9Q401")), .Names = c("Human", 
"Protein.IDs"), row.names = c(NA, 10L), class = "data.frame")

Поэтому я хочу сопоставить Protein.IDs в df_mouse с тем, где они существуют в df_mouse_human.В примерах данных я пытаюсь сопоставить A2ASS6; E9Q8N1; E9Q8K5; A2ASS6-2; A2AT70; F7CR78 с записью A2ASS6.Это работает хорошо, если я делаю это по-другому, но есть ли способ, чтобы, если часть шаблона соответствовала запросу, она возвращалась ИСТИНА?

Моя долгосрочная цель состоит в том, чтобы сопоставить и объединить данные, чтобы df_mouse получил новый столбец с совпадающими идентификаторами белка человека, а там, где нет совпадения, я просто заменю значение NA исходной строкой.идентификаторов мыши.

спасибо

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Один метод, который я обычно использую с частичными совпадениями, подобный этому, состоит в том, чтобы уменьшить более сложное поле, чтобы оно выглядело как более простое.Иногда это включает в себя просто удаление посторонних символов (например, если «совпадать только по первым четырем символам», тогда я создам новый индексный столбец из substr(idcol, 1, 4) и присоединяюсь к нему), но в этом случае это включает разрыв одной строки вкратный.

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

(ДляРади презентабельности / эстетики я изменяю df1, чтобы удалить другие инвариантные столбцы и, ради «других данных», добавляю столбец с номером строки.)

Я использую dplyrи tidyr, так:

library(dplyr)
library(tidyr)
df1 <- select(df1, Protein.IDs) %>%
  mutate(other = row_number())

Сначала я разбью 6-рядную рамку на гораздо большую:

df1ids <- tbl_df(df1) %>%
  select(Protein.IDs) %>%
  mutate(eachID = strsplit(Protein.IDs, ";")) %>%
  unnest()
df1ids
# # A tibble: 46 x 2
#    Protein.IDs                                        eachID  
#    <chr>                                              <chr>   
#  1 Q8CBM2;A2AL85;Q8BSY0                               Q8CBM2  
#  2 Q8CBM2;A2AL85;Q8BSY0                               A2AL85  
#  3 Q8CBM2;A2AL85;Q8BSY0                               Q8BSY0  
#  4 A2AMH3;A2AMH5;A2AMH4;Q6X893;Q6X893-2;A2AMH8        A2AMH3  
#  5 A2AMH3;A2AMH5;A2AMH4;Q6X893;Q6X893-2;A2AMH8        A2AMH5  
#  6 A2AMH3;A2AMH5;A2AMH4;Q6X893;Q6X893-2;A2AMH8        A2AMH4  
#  7 A2AMH3;A2AMH5;A2AMH4;Q6X893;Q6X893-2;A2AMH8        Q6X893  
#  8 A2AMH3;A2AMH5;A2AMH4;Q6X893;Q6X893-2;A2AMH8        Q6X893-2
#  9 A2AMH3;A2AMH5;A2AMH4;Q6X893;Q6X893-2;A2AMH8        A2AMH8  
# 10 A2AMW0;P47757-2;A2AMV7;P47757;F6QJN8;F6YHZ8;F7CAZ6 A2AMW0  
# # ... with 36 more rows

Обратите внимание, как выглядит первая строка из трехтри ряда по три.Мы будем использовать "eachID" для присоединения.

left_join(df1ids, df2, by = c("eachID" = "Protein.IDs")) %>%
  filter(complete.cases(.)) %>%
  select(Human, Protein.IDs) %>%
  right_join(df1)
# Joining, by = "Protein.IDs"
# # A tibble: 6 x 3
#   Human  Protein.IDs                                                  other
#   <chr>  <chr>                                                        <int>
# 1 <NA>   Q8CBM2;A2AL85;Q8BSY0                                             1
# 2 <NA>   A2AMH3;A2AMH5;A2AMH4;Q6X893;Q6X893-2;A2AMH8                      2
# 3 <NA>   A2AMW0;P47757-2;A2AMV7;P47757;F6QJN8;F6YHZ8;F7CAZ6               3
# 4 <NA>   Q3U8S1;A2APM5;A2APM3;A2APM4;E9QKM8;Q80X37;A2APM1;A2APM2;P15~     4
# 5 Q8WZ42 A2ASS6;E9Q8N1;E9Q8K5;A2ASS6-2;A2AT70;F7CR78                      5
# 6 <NA>   A2AUR7;Q9D031;Q01730                                             6

Если у вас есть несколько Human строк для каждого Proteins.IDs, все немного изменится.

df2$Protein.IDs[2] <- "E9Q8K5"
left_join(df1ids, df2, by = c("eachID" = "Protein.IDs")) %>%
  filter(complete.cases(.)) %>%
  select(Human, Protein.IDs) %>%
  right_join(df1)
# Joining, by = "Protein.IDs"
# # A tibble: 7 x 3
#   Human  Protein.IDs                                                  other
#   <chr>  <chr>                                                        <int>
# 1 <NA>   Q8CBM2;A2AL85;Q8BSY0                                             1
# 2 <NA>   A2AMH3;A2AMH5;A2AMH4;Q6X893;Q6X893-2;A2AMH8                      2
# 3 <NA>   A2AMW0;P47757-2;A2AMV7;P47757;F6QJN8;F6YHZ8;F7CAZ6               3
# 4 <NA>   Q3U8S1;A2APM5;A2APM3;A2APM4;E9QKM8;Q80X37;A2APM1;A2APM2;P15~     4
# 5 Q8WZ42 A2ASS6;E9Q8N1;E9Q8K5;A2ASS6-2;A2AT70;F7CR78                      5
# 6 Q8NF91 A2ASS6;E9Q8N1;E9Q8K5;A2ASS6-2;A2AT70;F7CR78                      5
# 7 <NA>   A2AUR7;Q9D031;Q01730                                             6

Примечаниекак у вас сейчас две копии other 5?Скорее всего, не то, что вы хотите.Если вы намереваетесь продолжить тему, разделенную точкой с запятой, то:

left_join(df1ids, df2, by = c("eachID" = "Protein.IDs")) %>%
  filter(complete.cases(.)) %>%
  group_by(Protein.IDs) %>%
  summarize(Human = paste(Human, collapse = ";")) %>%
  select(Human, Protein.IDs) %>%
  right_join(df1)
# Joining, by = "Protein.IDs"
# # A tibble: 6 x 3
#   Human       Protein.IDs                                             other
#   <chr>       <chr>                                                   <int>
# 1 <NA>        Q8CBM2;A2AL85;Q8BSY0                                        1
# 2 <NA>        A2AMH3;A2AMH5;A2AMH4;Q6X893;Q6X893-2;A2AMH8                 2
# 3 <NA>        A2AMW0;P47757-2;A2AMV7;P47757;F6QJN8;F6YHZ8;F7CAZ6          3
# 4 <NA>        Q3U8S1;A2APM5;A2APM3;A2APM4;E9QKM8;Q80X37;A2APM1;A2APM~     4
# 5 Q8WZ42;Q8N~ A2ASS6;E9Q8N1;E9Q8K5;A2ASS6-2;A2AT70;F7CR78                 5
# 6 <NA>        A2AUR7;Q9D031;Q01730                                        6
0 голосов
/ 16 октября 2018

@ r2evans задает хороший вопрос о том, что делать с несколькими совпадениями.Как только на этот вопрос ответят, мне, возможно, потребуется отредактировать мой ответ, но здесь есть быстрое решениеСначала мы разбиваем строку возможных идентификаторов, затем видим, какие идентификаторы сопоставляются в другом кадре данных, затем присоединяемся к индексу строки совпадения.

library(tidyverse)

df_mouse %>% mutate(all_id = str_split(Protein.IDs, ";"),
                    row = map(all_id, ~.x %in% df_mouse_human$Protein.IDs %>% which())) %>%
  unnest(row) %>%
  list(., df_mouse_human %>% rownames_to_column("row") %>% mutate(row = as.numeric(row))) %>%
  reduce(left_join, by = "row")
#>                                 Protein.IDs.x Replicate
#> 1 A2ASS6;E9Q8N1;E9Q8K5;A2ASS6-2;A2AT70;F7CR78         2
#>   Ratio.H.L.normalized.01 Ratio.H.L.normalized.02 Ratio.H.L.normalized.03
#> 1                     NaN                     NaN                     NaN
#>   row  Human Protein.IDs.y
#> 1   1 Q8WZ42        A2ASS6
...