如何在r中合并两个数据帧时保留索引

时间:2015-03-30 05:53:46

标签: r merge

我有两个数据帧:

> df1:
  a b
1 1 2
2 2 3
3 2 4
4 3 4
5 4 4
> df2:
  a b
1 1 1
2 1 2
3 2 3
4 3 4
5 5 5

然后合并df1和df2以获取df3,请注意合并by=c("a","b")

df3<-merge(df1,df2)
> df3
  a b
1 1 2
2 2 3
3 3 4

我想得到df1中选择的行索引,并在df1中添加一个列调用“label”。

   > df1:
      a b label    
    1 1 2  TRUE
    2 2 3  TRUE
    3 2 4 FALSE
    4 3 4  TRUE
    5 4 4 FALSE

我试过了:

df1$label<-apply(df1,1,function (x) ifelse(nrow(merge(x,df3))>0,TRUE,FALSE))

得到了错误的结果,因为我的df1非常大,所以速度很慢。 有什么简单的方法吗?像载体中的is.element?谢谢。

3 个答案:

答案 0 :(得分:1)

ab上合并,在SQL中执行等效的LEFT OUTER JOIN,然后为值FALSE分配不匹配的行:

df1 <- data.frame(a=c(1,2,2,3,4), b=c(2,3,4,4,4))
df2 <- data.frame(a=c(1,1,3,5), b=c(1,2,4,5))
df2$label <- TRUE                                  # df1 matches to df2 is TRUE
df3 <- merge(df1, df2, by=c("a", "b"), all.x=TRUE) # merge on a AND b 
df3$label[is.na(df3$label)] <- FALSE               # non-match is FALSE

输出:

> df3
  a b label
1 1 2  TRUE
2 2 3  TRUE
3 2 4 FALSE
4 3 4  TRUE
5 4 4 FALSE

答案 1 :(得分:1)

这是使用data.table的另一种方式:

require(data.table)
setkey(setDT(df1), a)                     ## (1)
idx = df1[df2, which=TRUE, nomatch=0L]    ## (2)
df1[, label := FALSE][idx, label := TRUE] ## (3)
df1
#    a b label
# 1: 1 2  TRUE
# 2: 2 3 FALSE
# 3: 3 4  TRUE
# 4: 4 5 FALSE
  1. setDT通过引用将data.frame转换为data.table。在data.table上,我们在setkey列上a - 它基本上按列a标记重新排序data.table df1 该列已排序。这是在步骤2中完成加入的先决条件。

  2. 我们会在x[i]x=df1之间执行i=df2表单的联接。 x必须是键控的 data.table,i可以是list,data.frame或data.table。联接在密钥列a上执行。对于 df2 的列a的每一行,我们找到匹配的行,并使用参数which=TRUE返回它们,如果不匹配,我们返回一个使用nomatch=0L为该行的“0”。

    在此步骤中,我们获得idx = 1, 3, 0。因为“1”和“3”匹配第一行和第三行,“5”不匹配。

  3. 我们将整个label列设置为FALSE,并仅将idx的行更新为TRUE(这些是匹配的行)。这是通过使用:=运算符再次引用(速度和内存效率)来完成的。

  4. 查看HTML vignettes了解详情。

答案 2 :(得分:0)

如果数据集很大,您也可以尝试data.table

 library(data.table)
 setkey(setDT(df2),a)[df1][,c('label','b') := 
                       list(!is.na(b), i.b)][,i.b:= NULL][]
 #    a b label
 #1: 1 2  TRUE
 #2: 2 3 FALSE
 #3: 3 4  TRUE
 #4: 4 5 FALSE