使用条件有效地连接两个数据表

时间:2016-06-22 00:22:21

标签: r dataframe

一个数据表(让我们的呼叫为A)包含ID号:

ID
3
5
12
8
...

和另一个表(让我们称之为B)包含该下限和上限以及该ID的名称。

ID_lower   ID_upper     Name
 1            4         James
 5            7         Arthur
 8            11        Jacob
 12           13        Sarah

基于表B,给定表A中的ID,我们可以通过在表B中的行上查找名称找到匹配的名称,以便

ID_lower <= ID <= ID upper

我想创建一个ID和Name表,所以在上面的例子中,它将是

ID           Name
3            James
5            Arthur
12           Sarah
8            Jacob
...          ...

我用于循环,因此对于A的每一行,我在B中查找行,使得ID位于该行的ID_lower和ID_upper之间,并从那里加入名称。 但是,这种方法有点慢。在R中有没有快速的方法?

4 个答案:

答案 0 :(得分:2)

在data.table的当前开发版本中使用新的non-equi连接功能,这很简单:

require(data.table) # v1.9.7+
dt2[dt1, .(ID, Name), on=.(ID_lower <= ID, ID_upper >= ID)]

请参阅devel版本here的安装说明。

其中,

dt1=fread('ID
            3
            5
           12
            8')
dt2 = fread('ID_lower   ID_upper     Name
                    1         4     James
                    5         7    Arthur
                    8        11     Jacob
                   12        13     Sarah')

答案 1 :(得分:1)

您可以使用第二个data.frame(B)制作一个查找表:

lu <- do.call(rbind,
              apply(B,1,function(x) 
                    data.frame(ID=c(x[1]:x[2]),Name=x[3], row.names = NULL)))

然后用你的第一个data.frame(A)查询它:

A$Name <- lu[A$ID,"Name"]

答案 2 :(得分:1)

您可以尝试此data.table解决方案:

data.table::setDT(B)[, .(Name, ID = Map(`:`, ID_lower, ID_upper))]
                    [, .(ID = unlist(ID)), .(Name)][ID %in% A$ID]

     Name ID
1:  James  3
2: Arthur  5
3:  Sarah 12
4:  Jacob  8

答案 3 :(得分:1)

我相信ID_lower A[,Name:=B[findInterval(ID,ID_lower),Name]]; A; ## ID Name ## 1: 3 James ## 2: 5 Arthur ## 3: 12 Sarah ## 4: 8 Jacob 可能是理想的方法:

B

只有当{1} ID_lowerA$ID排序并且(2)B中的所有值都被var bob = "bob" var joe = "joe" var arr = [bob, joe] arr[1] = "joseph" print(joe) // this returns "joe" and not sarah, because what happened is, arr is now equal to [bob, sarah] 中的范围所涵盖时,才会正确。< / p>