从 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
有问题的字符串示例 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