R语言拆分Intervar空格与等号分隔字符串 方括号内值单独分列
需求说明
现有R数据集结构如下:
structure(list(Intervar = c("Uncertain significance PVS1=0 PS=[0, 1, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 0, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Pathogenic PVS1=1 PS=[0, 1, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Likely benign PVS1=0 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 0, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 1, 0, 0, 1, 0]", "Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]" )), class = "data.frame", row.names = c(NA, -8L))
Intervar列每一行格式统一:开头为变异临床评级(Pathogenic/Likely pathogenic/Uncertain significance/Likely benign/Benign),后续为多个ACMG证据项赋值,分为两类:
- 单值类型:格式为
标识=数值,如PVS1=0 - 多值类型:格式为
标识=[数值1,数值2,...],如PS=[0,1,0,0,0]
需要将Intervar列拆分为多列:
- 单值类型直接生成对应列,列名取等号前的标识
- 多值类型中方括号内每个数值单独成列,列名为标识加序号,如PS对应PS1~PS5
期望输出示例:
PVS1 PS1 PS2 PS3 PS4 PS5 PM1 PM2 PM3 PM4 PM5 PM6 PM7 PP1 PP2 PP3 PP4 PP5 PP6 ... BP1 BP2 BP3 BP4 BP5 BP6 BP7 BP8 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ... 0 0 0 0 0 0 0 0 ...
此前实现代码会将方括号内数值求和后生成列,仅保留PS、PM等求和后的列,不符合需求:
test$Intervar %>% gsub(" (\\w+=)", "\n\\1", .) %>% paste0("\nDescription=", .) %>% gsubfn("\\[(.*?)\\]", ~ sum(scan(text = txt, sep = ",", quiet = TRUE)), .) %>% gsub("=", ": ", .) %>% textConnection %>% read.dcf %>% as.data.frame %>% type.convert
实现代码
以下是基于原有逻辑修改的版本,仅替换了方括号内的处理逻辑,将求和改为生成带序号的键值对:
library(gsubfn) library(magrittr) library(stringr) # 读取原始数据集 test <- structure(list(Intervar = c("Uncertain significance PVS1=0 PS=[0, 1, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 0, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Pathogenic PVS1=1 PS=[0, 1, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Likely benign PVS1=0 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 0, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 1, 0, 0, 1, 0]", "Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]", "Pathogenic PVS1=1 PS=[0, 0, 0, 0, 0] PM=[0, 1, 0, 0, 0, 0, 0] PP=[0, 0, 1, 0, 0, 0] BA1=0 BS=[0, 0, 0, 0, 0] BP=[0, 0, 0, 0, 0, 0, 0, 0]" )), class = "data.frame", row.names = c(NA, -8L)) # 核心处理 result <- test$Intervar %>% # 移除开头的临床评级 str_remove("^(Pathogenic|Likely pathogenic|Uncertain significance|Likely benign|Benign) ") %>% # 将多值项的[xxx]替换为带序号的键值对,如PS=[0,1,0]转为PS1=0 PS2=1 PS3=0 gsubfn("(\\w+)=\\[(.*?)\\]", function(key, val_str) { vals <- scan(text = val_str, sep = ",", quiet = TRUE) paste(paste0(key, seq_along(vals), "=", vals), collapse = " ") }, .) %>% # 原有格式转换逻辑 gsub(" (\\w+=)", "\n\\1", .) %>% paste0("\n", .) %>% textConnection() %>% read.dcf() %>% as.data.frame() %>% type.convert(as.is = TRUE) %>% # 按列名排序,可选 select(order(colnames(.)))
输出的result完全符合需求,单值项直接保留原标识作为列名,多值项自动生成带序号的列。
内容的提问来源于stack exchange,提问作者Lin Caijin
相关产品推荐
相关产品推荐

