按组从一个数据帧中的另一个数据帧中高效地查找数据

时间:2018-12-03 18:06:07

标签: r performance dataframe data.table lookup

我正在寻找以下问题的更快解决方案。

假设我有以下两个数据集。

df1 <- data.frame(Var1 = c(5011, 2484, 4031, 1143, 7412),
              Var2 = c(2161, 2161, 2161, 2161, 8595))
df2 <- data.frame(team=c("A","A", "B", "B", "B", "C", "C", "D", "D"),
              class=c("5011", "2161", "2484", "4031", "1143", "2161", "5011", "8595", "1143"),
              attribute=c("X1", "X2", "X1", "Z1", "Z2", "Y1", "X1", "Z1", "X2"),
              stringsAsFactors=FALSE)


> df1
  Var1 Var2
1 5011 2161
2 2484 2161
3 4031 2161
4 1143 2161
5 7412 8595

> df2
  team class attribute
1    A  5011        X1
2    A  2161        X2
3    B  2484        X1
4    B  4031        Z1
5    B  1143        Z2
6    C  2161        Y1
7    C  5011        X1
8    D  8595        Z1
9    D  1143        X2

我想知道df2中的哪些团队在class中与df1中的相对应。我对插入行的顺序不感兴趣。

我当前的代码(粘贴在下面)有效,但是效率很低。

一些规则:

  • 只有团队A和C在df1中排成一行的类中开会。
  • 团队B和团队D在df1中没有任何成对组合形式的班级中碰面。它们将从输出中排除。

代码:

    teams <- c()
    atts <- c()
    pxs <- unique(df2$team)

    for(j in pxs){
     subs <- subset(df2, team==j)
     for(i in 1:nrow(df1)){
      if(all(df1[i,] %in% subs$class)){
    teams <- rbind(teams, subs$team[i])
    atts <- rbind(atts, subs$attribute)
     } 
     }
    }

    output <- cbind(teams, atts)  

> output
     [,1] [,2] [,3]
[1,] "A"  "X1" "X2"
[2,] "C"  "Y1" "X1"

原始数据包括df1df2中的数百万行。

如何更有效地做到这一点?也许通过将applydata.table结合使用的方法?

1 个答案:

答案 0 :(得分:1)

不太清楚您的规则要达到的目的。

根据示例数据,代码和输出,您可能希望首先按df1的每一列进行联接,然后对2个结果进行内部联接:

library(data.table)
setDT(df1)
setDT(df2)[, cls := as.integer(cls)]

#left join df1 with df2 using Var1
v1 <- df2[df1, on=.(cls=Var1)]

#left join df1 with df2 using Var2
v2 <- df2[df1, on=.(cls=Var2)]

#inner join the 2 previous results to ensure that the same team is picked 
#where classes already match in v1 and v2
v1[v2, on=.(team, cls=Var1, Var2=cls), nomatch=0L]

输出:

   team  cls attribute Var2 i.attribute
1:    A 5011        X1 2161          X2
2:    C 5011        X1 2161          Y1