基于R dplyr中的数据库提取字符串

Extract strings based on a database in R dplyr

我想从我的数据中提取数据库中 L 和 R 字符串之间的字符串。

我的数据库包含 4 种不同的 L 和 R 字符串组合,我想测试所有这些组合。

一种方法是写一个for循环,但是有没有更优雅更巧妙的方法呢?

library(tidyverse)

data <-  c("CCACGAAGCTCTCCTACGTACGGTTATATTGACAGACCGAGGGCAGTCCAGCGCCAACCAGATAAGTGAAATCTAGTTCCA",
          "CCACGAAGCTCTCCTACGTACGGTTATATTGACAGACCGAGGGCAGTCCAGCGCCAACCAGATAAGTGAAATCTAGTTCCA",
          "CCACGAAGCTCTCCTAGGGGGGGGCTATTTTGGACTGCGTTACCAGTCCAGCGCCAACCAGATAAGTGGAATCTAGTTCGA",
          "CCACGTAGCTCTCCTCCGTGCGGTTATATTGACAGACCGAGGGCAGTCCAGCGCCAACCAGATAAGTGAAATCTAGTTCCA") %>% 
  as.data.frame() %>% 
  rename(seq=1)

database=data.frame(L=c("CTACG","CTAGG","CTCCG"), R=c("CAGTC","CAGTC","CAGTC"))


data %>% 
  mutate(extracts= str_extract(.$seq,
  str_c("(?<=",str_c(database[1,1], collapse = ""),").*(?=",str_c(database[1,2], collapse = ""),")")))
#>                                                                                 seq
#> 1 CCACGAAGCTCTCCTACGTACGGTTATATTGACAGACCGAGGGCAGTCCAGCGCCAACCAGATAAGTGAAATCTAGTTCCA
#> 2 CCACGAAGCTCTCCTACGTACGGTTATATTGACAGACCGAGGGCAGTCCAGCGCCAACCAGATAAGTGAAATCTAGTTCCA
#> 3 CCACGAAGCTCTCCTAGGGGGGGGCTATTTTGGACTGCGTTACCAGTCCAGCGCCAACCAGATAAGTGGAATCTAGTTCGA
#> 4 CCACGTAGCTCTCCTCCGTGCGGTTATATTGACAGACCGAGGGCAGTCCAGCGCCAACCAGATAAGTGAAATCTAGTTCCA
#>                    extracts
#> 1 TACGGTTATATTGACAGACCGAGGG
#> 2 TACGGTTATATTGACAGACCGAGGG
#> 3                      <NA>
#> 4                      <NA>

reprex package (v2.0.1)

创建于 2022-02-01

我会创建您独特的模式,然后应用到它们身上。然后,您可以 cbind 使用原始数据框获得结果。

library(stringr)

patterns <- paste0(database$L, "(.*)", database$R)

names(patterns) <- paste0("pattern", 1:3)

cbind(
  data,
  lapply(
    patterns,
    \(x) str_match(data$seq, x)[,2]
  )
)
#>                                                                                 seq
#> 1 CCACGAAGCTCTCCTACGTACGGTTATATTGACAGACCGAGGGCAGTCCAGCGCCAACCAGATAAGTGAAATCTAGTTCCA
#> 2 CCACGAAGCTCTCCTACGTACGGTTATATTGACAGACCGAGGGCAGTCCAGCGCCAACCAGATAAGTGAAATCTAGTTCCA
#> 3 CCACGAAGCTCTCCTAGGGGGGGGCTATTTTGGACTGCGTTACCAGTCCAGCGCCAACCAGATAAGTGGAATCTAGTTCGA
#> 4 CCACGTAGCTCTCCTCCGTGCGGTTATATTGACAGACCGAGGGCAGTCCAGCGCCAACCAGATAAGTGAAATCTAGTTCCA
#>                    pattern1                  pattern2                  pattern3
#> 1 TACGGTTATATTGACAGACCGAGGG                      <NA>                      <NA>
#> 2 TACGGTTATATTGACAGACCGAGGG                      <NA>                      <NA>
#> 3                      <NA> GGGGGGCTATTTTGGACTGCGTTAC                      <NA>
#> 4                      <NA>                      <NA> TGCGGTTATATTGACAGACCGAGGG

这只会捕获第一个匹配项。如果您需要捕获其他匹配项,可能会变得更复杂一些。我认为最简单的方法是生成您要检查的模式和序列的所有唯一组合,然后在 mutate() 中创建一个列表列。在这种情况下,我们可以使用您原来的 lookaheads/behinds 并使用 str_extract_all().

library(dplyr)
library(tidyr)

patterns <- paste0("(?<=", database$L, ")(.*)(?=", database$R, ")")
names(patterns) <- paste0("pattern", 1:3)

expand_grid(seq = data$seq,
            pattern = patterns) %>%
  distinct() %>%
  mutate(match = str_extract_all(seq, pattern)) %>%
  pivot_wider(
    names_from = "pattern",
    values_from = "match"
  ) %>%
  rename_with(~names(patterns),
              .cols = -seq)
#> # A tibble: 3 × 4
#>   seq                                                 pattern1 pattern2 pattern3
#>   <chr>                                               <list>   <list>   <list>  
#> 1 CCACGAAGCTCTCCTACGTACGGTTATATTGACAGACCGAGGGCAGTCCA… <chr>    <chr>    <chr>   
#> 2 CCACGAAGCTCTCCTAGGGGGGGGCTATTTTGGACTGCGTTACCAGTCCA… <chr>    <chr>    <chr>   
#> 3 CCACGTAGCTCTCCTCCGTGCGGTTATATTGACAGACCGAGGGCAGTCCA… <chr>    <chr>    <chr>