bio*_*ian 8 regex merge grep r dataframe
我正在尝试处理一些非常混乱的数据.我需要通过样本ID合并两个包含不同类型数据的大数据帧.问题是一个表的样本ID有许多不同的格式,但大多数都包含所需的ID字符串,用于匹配其ID中的某个位置,例如,一个表中的样本"1234"在另一个表中具有"ProjectB(1234)"的ID .
我做了一个简单的可重复的例子.
a<-data.frame(aID=c("1234","4567","6789","3645"),aInfo=c("blue","green","goldenrod","cerulean"))
b<-data.frame(bID=c("4567","(1234)","6789","23645","63528973"), bInfo=c("apple","banana","kiwi","pomegranate","lychee"))
Run Code Online (Sandbox Code Playgroud)
使用merge可以获得部分方法:
merge(a,b, by.x="aID", by.y="bID", all=TRUE)
aID aInfo bInfo
1 1234 blue <NA>
2 3645 cerulean <NA>
3 4567 green apple
4 6789 goldenrod kiwi
5 (1234) <NA> banana
6 23645 <NA> pomegranate
7 63528973 <NA> lychee
Run Code Online (Sandbox Code Playgroud)
但是喜欢的输出基本上是:
ID aInfo bInfo
1 1234 blue banana
2 3645 cerulean pomegranate
3 4567 green apple
4 6789 goldenrod kiwi
5 63528973 <NA> lychee
Run Code Online (Sandbox Code Playgroud)
我只是想知道是否有办法将grep纳入这个或另一个R-tastic方法?
提前致谢
根据条件进行操作merge有点棘手。我不认为你可以按照merge编写的那样来做到这一点,所以你最终不得不用 编写一个自定义函数by。这是相当低效的,但是,也是如此merge。如果您有数百万行,请考虑data.table. 这就是执行“内部联接”的方式,其中仅返回匹配的行。
# I slightly modified your data to test multiple matches
a<-data.frame(aID=c("1234","1234","4567","6789","3645"),aInfo=c("blue","blue2","green","goldenrod","cerulean"))
b<-data.frame(bID=c("4567","(1234)","6789","23645","63528973"), bInfo=c("apple","banana","kiwi","pomegranate","lychee"))
f<-function(x) merge(x,b[agrep(x$aID[1],b$bID),],all=TRUE)
do.call(rbind,by(a,a$aID,f))
# aID aInfo bID bInfo
# 1234.1 1234 blue (1234) banana
# 1234.2 1234 blue2 (1234) banana
# 3645 3645 cerulean 23645 pomegranate
# 4567 4567 green 4567 apple
# 6789 6789 goldenrod 6789 kiwi
Run Code Online (Sandbox Code Playgroud)
进行完全连接有点棘手。这是一种方法,但效率仍然很低:
f<-function(x,b) {
matches<-b[agrep(x[1,1],b[,1]),]
if (nrow(matches)>0) merge(x,matches,all=TRUE)
# Ugly... but how else to create a data.frame full of NAs?
else merge(x,b[NA,][1,],all.x=TRUE)
}
d<-do.call(rbind,by(a,a$aID,f,b))
left.over<-!(b$bID %in% d$bID)
rbind(d,do.call(rbind,by(b[left.over,],'bID',f,a))[names(d)])
# aID aInfo bID bInfo
# 1234.1 1234 blue (1234) banana
# 1234.2 1234 blue2 (1234) banana
# 3645 3645 cerulean 23645 pomegranate
# 4567 4567 green 4567 apple
# 6789 6789 goldenrod 6789 kiwi
# bID <NA> <NA> 63528973 lychee
Run Code Online (Sandbox Code Playgroud)
在合并之前我会再清理一下你的 bID。如果您知道 bID 格式化的所有奇怪方式,那么使用 清理它们应该很简单gsub()。
在你的例子中,要删除括号,我会做类似的事情
expr <- '\\((.*)\\)'
b$bID <- gsub(expr, replace='\\1', b$bID)
Run Code Online (Sandbox Code Playgroud)
里面expr发生了一些事情。首先,它是.*任何字符任意次数的正则表达式。将其括在括号中可以让我们gsub知道我们想要保留它并且可以在替换表达式中引用它。为了将左括号和右括号用作实际字符,我们需要用双反斜杠对其进行转义。把所有这些放在一起可以读作:我想将所有内容保留在左括号和右括号之间。
请注意,您可以使用替换表达式做一些奇特的事情,例如replace='id_\\1'.
关于在数字序列中查找 ID,您必须尝试子字符串匹配或其他方法,但我认为这不是一个好方法。
希望这可以帮助。
| 归档时间: |
|
| 查看次数: |
2704 次 |
| 最近记录: |