1.需求
两个数据框,都有gene列,可以连接到一起,而具体基因的大小写有所不同,连接时就无法匹配上。一个可行办法是,将两者都变成全部大写,或全部小写进行连接。但有的情境下这个大小写是有意义的,连接后再改回去比较麻烦。
library(dplyr)
a = data.frame(gene = paste0("Gene",8:15),
change = sample(c("up","down"),8,replace = T),
score = sample(1:100,8))
head(a)
## gene change score
## 1 Gene8 down 60
## 2 Gene9 up 37
## 3 Gene10 up 58
## 4 Gene11 up 24
## 5 Gene12 up 74
## 6 Gene13 up 19
b = data.frame(gene = paste0("gENE",sample(1:12,12)),
pvalue = round(runif(12),2))
head(b)
## gene pvalue
## 1 gENE11 0.39
## 2 gENE6 0.81
## 3 gENE3 0.40
## 4 gENE9 0.19
## 5 gENE4 0.46
## 6 gENE5 0.48
merge(a,b,by = "gene")
## [1] gene change score pvalue
## <0 rows> (or 0-length row.names)
inner_join(a,b,by = "gene")
## [1] gene change score pvalue
## <0 rows> (or 0-length row.names)
2.解决办法
搜索定位到fuzzyjoin这个包,有忽略大小写的参数
if(!require(fuzzyjoin))install.packages("fuzzyjoin")
library(fuzzyjoin)
dat = regex_inner_join(a,b,by = "gene",ignore_case =TRUE)
dat
## gene.x change score gene.y pvalue
## 1 Gene8 down 60 gENE8 0.98
## 2 Gene9 up 37 gENE9 0.19
## 3 Gene10 up 58 gENE1 0.54
## 4 Gene10 up 58 gENE10 0.60
## 5 Gene11 up 24 gENE11 0.39
## 6 Gene11 up 24 gENE1 0.54
## 7 Gene12 up 74 gENE12 0.58
## 8 Gene12 up 74 gENE1 0.54
## 9 Gene13 up 19 gENE1 0.54
## 10 Gene14 up 26 gENE1 0.54
## 11 Gene15 up 13 gENE1 0.54
本以为到这里就结束了,仔细一看其实有问题。这个函数有部分匹配的属性,比如gene1和gene10,gene11,gene12都匹配上了!
那不行奥。没有参数,所以只能自己再把错配的去掉了。
identical(dat$gene.x,dat$gene.y)
## [1] FALSE
也没有参数可设置。所以我又去搜索到了一个与identical类似的函数strcmpi,可以忽略大小写的。本以为它可以向量化运算,可他不能。所以用循环挨个判断好了。
library(pracma)
table(strcmpi(dat$gene.x,dat$gene.y))
##
## FALSE
## 1
k = apply(dat,1,function(i){
strcmpi(i[1],i[4])
})
table(k)
## k
## FALSE TRUE
## 6 5
dat = dat[k,]
dat
## gene.x change score gene.y pvalue
## 1 Gene8 down 60 gENE8 0.98
## 2 Gene9 up 37 gENE9 0.19
## 4 Gene10 up 58 gENE10 0.60
## 5 Gene11 up 24 gENE11 0.39
## 7 Gene12 up 74 gENE12 0.58
这样就解决了错配的问题。
3.组合起来写个新函数
imerge = function(x,y,by){
dat = fuzzyjoin::regex_inner_join(x,y,by = by,ignore_case =TRUE)
if(is.null(names(by))){
i = which(colnames(x)==by)
}else{
i = which(colnames(x)==names(by))
}
j = which(colnames(y)==by)+ncol(x)
k = apply(dat,1,function(z){
strcmpi(z[i],z[j])
})
dat = dat[k,]
return(dat)
}
imerge(a,b,by = "gene")
## gene.x change score gene.y pvalue
## 1 Gene8 down 60 gENE8 0.98
## 2 Gene9 up 37 gENE9 0.19
## 4 Gene10 up 58 gENE10 0.60
## 5 Gene11 up 24 gENE11 0.39
## 7 Gene12 up 74 gENE12 0.58
# 不同列名也可以
k = b
colnames(k)[1]="GENE"
imerge(a,k,by = c("gene"="GENE"))
## gene change score GENE pvalue
## 1 Gene8 down 60 gENE8 0.98
## 2 Gene9 up 37 gENE9 0.19
## 4 Gene10 up 58 gENE10 0.60
## 5 Gene11 up 24 gENE11 0.39
## 7 Gene12 up 74 gENE12 0.58
哈。搞定咯。
网友评论