【问题标题】:Creating multiple rows from a complex string in R从R中的复杂字符串创建多行
【发布时间】:2022-01-20 23:20:14
【问题描述】:

名为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

最终结果是一张桌子:

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 块拆分为自己的行的帮助将不胜感激!

一切顺利

【问题讨论】:

    标签: r string dplyr tidyr


    【解决方案1】:

    使用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
    

    【讨论】:

    • 非常感谢您抽出宝贵的时间来回答,这非常有效,但我接受了下面的答案,因为它允许 REF 和 ALT 可能比单个字母更长。 ATT等
    【解决方案2】:

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

    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”

    要使其成为表格,我们可以将其再次拆分为“:”、“/”或“_”并转换为数据框。由于有多个字符串和多个分割点,参数simplify=T给我们一个矩阵(每行是x中的一个字符串,每列是分割后的一块),可以转换成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
    

    【讨论】:

    • 非常感谢您抽出宝贵时间来回答,这非常有效,我接受了它,因为它还允许 REF ALT 长度超过一个字母。
    【解决方案3】:

    另一种可能的解决方案:

    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
    

    【讨论】:

    • 非常感谢您抽出宝贵的时间来回答,这真的很好!
    • 不客气,@tacrolimus!
    猜你喜欢
    • 2022-12-17
    • 2011-11-25
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    • 2021-12-24
    • 2019-11-14
    • 2021-04-30
    • 1970-01-01
    相关资源
    最近更新 更多