从 R 中的复杂字符串创建多行

Creating multiple rows from a complex string in R

有问题的字符串示例 gene_snps:

"ultra_rare_variant_chr9:23143143_A/C_chr9:5322432_G/T_chr9:9840984342_T/C;chr9:5324234:G/T;chr9:324424_T/A" 

期望的结果:

markerID
chr9:23143143_A/C
chr9:5322432_G/T
chr9:9840984342_T/C
chr9:5324234:G/T
chr9:324424_T/A

最终结果是 table:

CHR POS REF ALT
chr9 23143143 A C
chr9 5322432 G T
chr9 9840984342 T C
chr9 5324234 G T
chr9 324424 T A

当它们只是“;”时,我曾经有一个代码将它们分开分隔使用:

x <- separate_rows(gene_snps, markerIDs, sep=c(";"))
x <- separate_rows(x, col="markerIDs", into=c("pos", "ref_alt"), sep=c("_"))
x <- separate_rows(x, col="pos", into=c("CHR", "POS"), sep=c(":"))
x <- separate_rows(x, col="ref_alt", into=c("REF", "ALT"), sep=c("/"))

但现在已经过时了,因为用于生成代码的上游工具现在引入了“ultra_rare”标签,该标签全部由“_”分隔。

任何帮助拆分此字符串以摆脱 ultra_rare_variant 位并将每个 chrx:x_x/x 块拆分到它自己的行中的任何帮助将不胜感激!

祝一切顺利

我们只需要使用具有前瞻性的正则表达式:

library(stringr)

x = str_split(str, '[_;](?=chr)', simplify = T)[-1]
x

[1] "chr9:23143143_A/C"   "chr9:5322432_G/T"    "chr9:9840984342_T/C" "chr9:5324234:G/T"   
[5] "chr9:324424_T/A"    
  

这匹配“_”或“;”立即进行“chr”,然后使用它来拆分字符串。参数 simplify=T 使它以向量而不是列表的形式给出结果,我们使用 [-1] 删除第一个元素,即“ultra_rare_variant”

要使其成为 table,我们可以在“:”、“/”或“_”上再次拆分它并转换为数据帧。由于有多个字符串和多个分割点,参数simplify=T给了我们一个矩阵([=15=中每一行是一个字符串,分割后每一列是一块),可以转换成一个data.frame:

tbl <- as.data.frame(str_split(x, '[:_/]', simplify = TRUE))

colnames(tbl) <- c('CHR', 'POS', 'REF','ALT') # Set column names
tbl

   CHR        POS REF ALT
1 chr9   23143143   A   C
2 chr9    5322432   G   T
3 chr9 9840984342   T   C
4 chr9    5324234   G   T
5 chr9     324424   T   A

另一个可能的解决方案:

library(tidyverse)

s <- "ultra_rare_variant_chr9:23143143_A/C_chr9:5322432_G/T_chr9:9840984342_T/C;chr9:5324234:G/T;chr9:324424_T/A" 

data.frame(CHR = s %>% str_remove("ultra_rare_variant_")) %>% 
  separate_rows(CHR, sep=";|_(?=chr9)") %>% 
  separate(CHR, into = c("CHR","POS","REF","ALT"), sep=":|_|/")

#> # A tibble: 5 × 4
#>   CHR   POS        REF   ALT  
#>   <chr> <chr>      <chr> <chr>
#> 1 chr9  23143143   A     C    
#> 2 chr9  5322432    G     T    
#> 3 chr9  9840984342 T     C    
#> 4 chr9  5324234    G     T    
#> 5 chr9  324424     T     A

使用 stringr::str_match_all 将所有内容直接保存到命名的捕获组中。

x <- "ultra_rare_variant_chr9:23143143_A/C_chr9:5322432_G/T_chr9:9840984342_T/C;chr9:5324234:G/T;chr9:324424_T/A"
pattern <- "(?<CHR>chr\d)?[_:/](?<POS>\d+)?[_:/](?<REF>[A-Z])?[_:/](?<ALT>[A-Z])?"
as.data.frame(stringr::str_match_all(x, pattern)[[1L]][, -1L])

输出

   CHR        POS REF ALT
1 chr9   23143143   A   C
2 chr9    5322432   G   T
3 chr9 9840984342   T   C
4 chr9    5324234   G   T
5 chr9     324424   T   A