Regex R两个逗号分隔字符串之间的匹配
我试图找到一种优雅的方法来查找数据帧中以下两个字符列之间的匹配。复杂的部分是,任何一个字符串都可以包含一个逗号分隔的列表,如果一个列表的一个成员与另一个列表的任何成员匹配,那么整个条目都将被视为匹配项。我不确定我解释得有多好,所以这里是示例数据和输出: 备选案文1:Regex R两个逗号分隔字符串之间的匹配,regex,r,pattern-matching,match,Regex,R,Pattern Matching,Match,我试图找到一种优雅的方法来查找数据帧中以下两个字符列之间的匹配。复杂的部分是,任何一个字符串都可以包含一个逗号分隔的列表,如果一个列表的一个成员与另一个列表的任何成员匹配,那么整个条目都将被视为匹配项。我不确定我解释得有多好,所以这里是示例数据和输出: 备选案文1: 在 A G CGTCC,AT CGC 备选案文2: AA A GG 在,GGT CG 每行的预期匹配: 第1行=无 第2行=A 第3行=无 第4行=AT 第5行=无 非工作解决方案: 第一次尝试:按所需列合并整个数据帧,
- 在
- A
- G
- CGTCC,AT
- CGC
- AA
- A
- GG
- 在,GGT
- CG
- 第1行=无
- 第2行=A
- 第3行=无
- 第4行=AT
- 第5行=无
match1 = data.frame(merge(vcf.df, ref.df, by=c("chr", "start", "end", "ref")))
matches = unique(match1[unlist(sapply(match1$Alt1 grep, match1$Alt2, fixed=TRUE)),])
第二种方法,使用VariantAnoatation/Granges中的FindVerlaps特征:
findoverlaps(ranges(vcf1), ranges(vcf2))
如有任何建议,将不胜感激!谢谢大家!
解决方案
感谢@Marat Talipov在下面的回答,以下解决方案可用于比较两个逗号分隔的字符串:
> ##read in edited kaviar vcf and human ref
> ref <- readVcfAsVRanges("ref.vcf.gz", humie_ref)
Warning message:
In .vcf_usertag(map, tag, ...) :
ScanVcfParam ‘geno’ fields not present: ‘AD’
> ##rename chromosomes to match with vcf files
> ref <- renameSeqlevels(ref, c("1"="chr1"))
> ##################################
> ## Gather VCF files to process ##
> ##################################
> ##data frame *.vcf.gz files in directory path
> vcf_path <- data.frame(path=list.files(vcf_dir, pattern="*.vcf.gz$", full=TRUE))
> ##read in everything but sample data for speediness
> vcf_param = ScanVcfParam(samples=NA)
> vcf <- readVcfAsVRanges("test.vcf.gz", humie_ref, param=vcf_param)
> #################
> ## Match SNP's ##
> #################
> ##create data frames of info to match on
> vcf.df = data.frame(chr =as.character(seqnames(vcf)), start = start(vcf), end = end(vcf), ref = as.character(ref(vcf)),
+ alt=alt(vcf), stringsAsFactors=FALSE)
> ref.df = data.frame(chr =as.character(seqnames(ref)), start = start(ref), end = end(ref),
+ ref = as.character(ref(ref)), alt=alt(ref), stringsAsFactors=FALSE)
>
> ##merge based on all positional fields except vcf
> col_match = data.frame(merge(vcf.df, ref.df, by=c("chr", "start", "end", "ref")))
> library(stringi)
> ##split each alt column by comma and bind together
> M1 <- stri_list2matrix(sapply(col_match$alt.x,strsplit,','))
> M2 <- stri_list2matrix(sapply(col_match$alt.y,strsplit,','))
> M <- rbind(M1,M2)
> ##compare results
> result <- apply(M,2,function(z) unique(na.omit(z[duplicated(z)])))
> ##add results column to col_match df for checking/subsetting
> col_match$match = result
> head(col_match)
chr start end ref alt.x alt.y match
1 chr1 39998059 39998059 A G G G
2 chr1 39998059 39998059 A G G G
3 chr1 39998084 39998084 C A A A
4 chr1 39998084 39998084 C A A A
5 chr1 39998085 39998085 G A A A
6 chr1 39998085 39998085 G A A A
##阅读编辑的kaviar vcf和人类参考
>ref##重命名染色体以与vcf文件匹配
>参考号##################################
>##收集VCF文件以进行处理##
> ##################################
>##数据框*.vcf.gz目录路径中的文件
>vcf#U路径##读取除样本数据外的所有数据以提高速度
>vcf_参数=扫描vcf参数(样本=NA)
>vcf#################
>##匹配SNP的##
> #################
>##创建要匹配的信息数据帧
>vcf.df=data.frame(chr=as.character(seqnames(vcf)),start=start(vcf),end=end(vcf),ref=as.character(ref(vcf)),
+alt=alt(vcf),stringsAsFactors=FALSE)
>ref.df=data.frame(chr=as.character(seqnames(ref)),start=start(ref),end=end(ref),
+ref=as.character(ref(ref)),alt=alt(ref),stringsAsFactors=FALSE)
>
>##基于除vcf以外的所有位置字段合并
>col_match=data.frame(合并(vcf.df,ref.df,by=c(“chr”,“start”,“end”,“ref”))
>图书馆(stringi)
>##用逗号拆分每个alt列并绑定在一起
>M1 M2 M##比较结果
>结果##将结果列添加到列匹配df以进行检查/子集设置
>col_match$match=结果
>头部(col_匹配)
chr开始结束参考alt.x alt.y匹配
1 chr1 39998059 39998059 A G G
2 chr1 39998059 39998059 A G G
3 chr1 39998084 39998084 C A A
4 chr1 39998084 39998084 C A A
5 chr1 39998085 39998085 G A A
6 chr1 39998085 39998085 G A A
如果输入列表长度相等,并且希望以成对方式比较列表元素,则可以使用以下解决方案:
library(stringi)
M1 <- stri_list2matrix(sapply(Alt1,strsplit,','))
M2 <- stri_list2matrix(sapply(Alt2,strsplit,','))
M <- rbind(M1,M2)
result <- apply(M,2,function(z) unique(na.omit(z[duplicated(z)])))
你可以这样做:
Alt1 <- list('AT','A','G',c('CGTCC','AT'),'CGC')
Alt2 <- list('AA','A','GG',c('AT','GGT'),'CG')
# make sure you change the lists within in the lists into vectors
matchlist <- list()
for (i in 1:length(Alt1)){
matchlist[[i]] <- ifelse(Alt1[[i]] %in% Alt2[[i]],
paste("Row",i,"=",c(Alt1[[i]],Alt2[[i]])[duplicated(c(Alt1[[i]],Alt2[[i]]))],sep=" "),
paste("Row",i,"= none",sep=" "))
}
print(matchlist)
Alt1坚持使用stringi
包,您可以使用来自Marat答案的Alt1
和Alt2
数据执行类似操作
library(stringi)
f <- function(x, y) {
ssf <- stri_split_fixed(c(x, y), ",", simplify = TRUE)
if(any(sd <- stri_duplicated(ssf))) ssf[sd] else NA_character_
}
Map(f, Alt1, Alt2)
# [[1]]
# [1] NA
#
# [[2]]
# [1] "A"
#
# [[3]]
# [1] NA
#
# [[4]]
# [1] "AT"
#
# [[5]]
# [1] NA
#
# [[6]]
# [1] "GG" "CC"
Alt1和Alt2的长度相等吗?既然您使用的是“stringi”,为什么不使用stri_split
,直接简化为一个矩阵?那么mapply(match,Alt1,Alt2)
呢?@AnandaMahto,因为stri_list2matrix
是我在stringi
)度量中知道的唯一函数,它将只返回完全匹配的结果。问题还在于匹配逗号分隔子字符串。另外,我的输入列表长度不同。有没有办法修改它以适应不同的长度?这是一个很好的方法。。。谢谢。我想你可以用交叉(Alt1[[I]],Alt2[[I]])替换(Alt2[[I]]]%替换%Alt1[[I]])
(Alt1[[I]],Alt2[[I]])
我想你是对的!谢谢我现在不在r附近,我将稍后再试。我尝试了上述两种建议,收到了以下错误:ifelse中的错误((Alt1[[I]]%在%Alt2[[I]]中)|(Alt2[[I]]%在%Alt1[[I]]中);:在为函数“ifelse”选择方法时评估参数“yes”时出错:在c中出错(Alt1[[I]],Alt2[[I]])[[any(重复的)(c(Alt1[[I]],Alt2[[i]])]]:尝试选择少于一个元素>打印(匹配列表)列表()
您确定alt1和Alt2是列表,如果是,它们的长度是否相同?太棒了,我来试一试!
Alt1 <- list('AT','A','G',c('CGTCC','AT'),'CGC')
Alt2 <- list('AA','A','GG',c('AT','GGT'),'CG')
# make sure you change the lists within in the lists into vectors
matchlist <- list()
for (i in 1:length(Alt1)){
matchlist[[i]] <- ifelse(Alt1[[i]] %in% Alt2[[i]],
paste("Row",i,"=",c(Alt1[[i]],Alt2[[i]])[duplicated(c(Alt1[[i]],Alt2[[i]]))],sep=" "),
paste("Row",i,"= none",sep=" "))
}
print(matchlist)
library(stringi)
f <- function(x, y) {
ssf <- stri_split_fixed(c(x, y), ",", simplify = TRUE)
if(any(sd <- stri_duplicated(ssf))) ssf[sd] else NA_character_
}
Map(f, Alt1, Alt2)
# [[1]]
# [1] NA
#
# [[2]]
# [1] "A"
#
# [[3]]
# [1] NA
#
# [[4]]
# [1] "AT"
#
# [[5]]
# [1] NA
#
# [[6]]
# [1] "GG" "CC"
g <- function(x, y, sep = ",") {
s <- scan(text = c(x, y), what = "", sep = sep, quiet = TRUE)
s[duplicated(s)]
}
Map(g, Alt1, Alt2)