R合并数据帧,允许不精确的ID匹配(例如,附加字符1234匹配ab1234)

时间:2014-01-16 14:59:36

标签: regex r merge grep 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"))

使用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

但是喜欢的输出基本上是:

        ID     aInfo       bInfo
1     1234      blue      banana
2     3645  cerulean pomegranate
3     4567     green       apple
4     6789 goldenrod        kiwi
5 63528973      <NA>      lychee

我只是想知道是否有办法将grep合并到这个或另一个R-tastic方法中?

提前致谢

3 个答案:

答案 0 :(得分:3)

在条件上执行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

进行完全加入有点棘手。这是一种方式,效率仍然很低:

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

答案 1 :(得分:1)

在合并之前,我会更多地清理你的bID。如果您知道bID格式化的所有奇怪方式,那么使用gsub()清理它们应该很简单。

在您的示例中,要删除括号,我会执行类似

的操作
expr <- '\\((.*)\\)'
b$bID <- gsub(expr, replace='\\1', b$bID)

expr中,有一些事情正在发生。首先,.*是任何字符的regexp。用括号括起来让gsub知道我们想保留它并且可以在替换表达式中引用它。为了使用左右括号作为实际字符,我们需要使用双反斜杠来转义它们。把所有这些放在一起就会读作;我想把所有东西放在左括号和右括号之间。

请注意,您可以使用替换表达式执行奇特的操作,例如replace='id_\\1'

关于在数字序列中查找ID,您必须尝试子字符串匹配或其他东西,但我不认为这是一个好方法。

希望这有帮助。

答案 2 :(得分:1)

这是使用## Create example tables; I added the sarcoline cases ## so there would be examples of rows in a but not b a <- data.table(aID=c("1234","1234","4567","6789","3645","321", "321"), aInfo=c("blue","blue2","green","goldenrod","cerulean", "sarcoline","sarcoline2"), key="aID") b <- data.table(bID=c("4567","(1234)","6789","23645","63528973"), bInfo=c("apple","banana","kiwi","pomegranate","lychee"), key="bID") ## Use agrep to get the rows of b by each aID from a ab <- a[, b[agrep(aID, bID)], by=.(aID, aInfo)] ab ## aID aInfo bID bInfo ## 1: 1234 blue (1234) banana ## 2: 1234 blue2 (1234) banana ## 3: 3645 cerulean 23645 pomegranate ## 4: 4567 green 4567 apple ## 5: 6789 goldenrod 6789 kiwi 的答案,灵感来自@nograpes。

ab <- rbindlist(list(ab, a[!ab[, unique(aID)]], b[!ab[, unique(bID)]]), fill=TRUE)

到目前为止,我们只有一个内连接,所以现在让我们添加原始表中不匹配的行:

## Update NA values of aID with the value from bID
ab[is.na(aID), aID:=bID]

## Drop the bID column
ab[, bID:=NULL]

这些步骤是可选的,包含在内以匹配OP的输出:

ab
##         aID      aInfo       bInfo
## 1:     1234       blue      banana
## 2:     1234      blue2      banana
## 3:     3645   cerulean pomegranate
## 4:     4567      green       apple
## 5:     6789  goldenrod        kiwi
## 6:      321  sarcoline          NA
## 7:      321 sarcoline2          NA
## 8: 63528973         NA      lychee

最终结果

    function plotTrendData(data)
{
    $.ajax({
        type: 'GET',
        url: '/your url goes here/',
        data: { requestData: data },
        contentType: "application/json; charset=utf-8",
        dataType: 'json',
        success: function (data)
        {
            if (data.length > 4) {
                prepareChartData(data);
                if (myChart === null) {
                    plotChartData(dataSeries, xTitle);
                }
                else {
                    addChartSeries(dataSeries, xTitle);
                }
            }
        }
    });
}