【问题标题】:Match part of a pattern to a string将模式的一部分与字符串匹配
【发布时间】:2019-03-20 10:09:55
【问题描述】:

我有两个数据框,我想做一个匹配和合并。 最初我使用的是 inner_join 和 coalesce,但意识到匹配部分没有正确匹配。

我找到了一个似乎方向正确的示例 How to merge two data frame based on partial string match with 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")

所以我想将df_mouse 中的 Protein.ID 与它们在df_mouse_human 中存在的位置相匹配。在示例数据中,我尝试将 A2ASS6;E9Q8N1;E9Q8K5;A2ASS6-2;A2AT70;F7CR78 与条目 A2ASS6 匹配。如果我以另一种方式进行操作,效果会很好,但是有没有一种方法可以让模式的一部分与查询匹配,它会返回 TRUE?

我的长期目标是匹配和合并数据,以便 df_mouse 获得一个具有匹配人类蛋白质 ID 的新列,如果没有匹配,我将用原始的鼠标 ID 字符串替换 NA 值.

谢谢

【问题讨论】:

  • 您可能会有多个匹配项(在您的真实数据中),您打算输出什么?另外,您对样本数据提出了一个很好的问题,但是那里的所有内容中只有一个匹配项,那是否具有代表性?也就是说(根据我的第一个问题),如果您实际上连续获得两个 Human 匹配项,您打算发生什么?

标签: r merge pattern-matching


【解决方案1】:

我常用的部分匹配方法是减少更复杂的字段,使其看起来更简单。有时这仅涉及删除无关字符(例如,如果“仅在前四个字符上匹配”,那么我将从 substr(idcol, 1, 4) 创建一个新的索引列并加入),但在这种情况下,它涉及将一个字符串分解为多个。

这涉及将每个以分号分隔的 id 与大字符串相关联,使这个中间帧比原始数据更高(有时更高)。

(为了美观/美观,我正在修改 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

如果每个Proteins.IDs 碰巧有多个Human 行,情况会发生一些变化。

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

【讨论】:

  • 嗨,将值带回分号分隔的主题是理想的。小鼠数据仅表明特定的肽序列可能属于 x 个不同的蛋白质 id 之一,因此返回应该是它可能映射到的 x 个人类蛋白质 id。感谢您的解决方案!
【解决方案2】:

@r2evans 提出了一个关于如何处理多个匹配项的好问题。一旦这个问题得到回答,我可能需要编辑我的答案,但这里有一个快速的解决方案。首先,我们拆分可能的 ID 字符串,然后我们查看在另一个数据帧中匹配哪些 ID,然后我们加入匹配的行索引。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 2014-03-22
    • 1970-01-01
    • 2015-12-31
    相关资源
    最近更新 更多