忽略大小写的“merge”

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

哈。搞定咯。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容