更有效地将匹配列与data.table中的重复项合并

时间:2014-12-30 22:16:24

标签: r merge data.table

我有两个data.table,两个共享一个变量;我正在尝试添加一个在第二个中缺失的变量,但该变量与共享变量一对一地绑定。

这显然是一个合并,但由于共享变量有多个实例,我不得不使用感觉变通方法来合并新变量。

让我们具体一点。

x <- data.table(let = rep(letters[1:3], 2:4),
                num = rep(1:3, 2:4), other = rnorm(9))
y <- data.table(let = rep(c("a", "c"), c(10, 6)))

x:
   let num       other
1:   a   1 -0.41695882
2:   a   1 -0.59875888
3:   b   2 -0.19433915
4:   b   2  0.58406046
5:   b   2 -0.33922321
6:   c   3 -0.63076561
7:   c   3  1.06987710
8:   c   3  0.08869372
9:   c   3 -1.31196123

y:
    let
 1:   a
 2:   a
 3:   a
 4:   a
 5:   a
 6:   a
 7:   a
 8:   a
 9:   a
10:   a
11:   c
12:   c
13:   c
14:   c
15:   c
16:   c

我只想将num列添加到y;由于numlet匹配为1-1,因此重复项并不重要。

这是一种有效的方法;我感觉有一些更简单的东西。

setkey(x, let)
setkey(y, let)

y <- x[!duplicated(let), c("let", "num"), with = FALSE][y]

3 个答案:

答案 0 :(得分:7)

我能想到的唯一改进是

  1. 您可以跳过setkey(x, let)部分

  2. 您还可以通过引用更新y(而不是使用<-创建副本,然后分配回y

  3. 如果您使用的是当前稳定版本的data.table(v <= 1.9.4),则必须使用allow.cartesian = TRUE

    setkey(y,let)
    y[x[!duplicated(let)], num := i.num, allow.cartesian = TRUE][]
    

    您也可以使用unique代替duplicated(他们都有data.table方法)

    y[unique(x, by = "let"), num := i.num, allow.cartesian = TRUE]
    

    这是使用新.EACHI方法的另一种可能性,尽管此处不需要使用by=.EACHI。我已经向您展示了为您公开此功能。请查看this post以获取有关此功能以及何时有用的详细说明。

    y[x, num := unique(i.num), by = .EACHI, allow.cartesian = TRUE]
    

    编辑 :(感谢@Arun指出这一点)

    我们不应该在这里需要allow.cartesian参数,因为i中没有重复项。实际上,it's a bug, #742已经修复了current development version (1.9.5)。所以你只需要这样做:

    y[x[!duplicated(let)], num := i.num]
    # or
    y[unique(x, by = "let"), num := i.num]
    # or (though not recommended in this specific case)
    y[x, num := unique(i.num), by = .EACHI]
    

答案 1 :(得分:2)

好吧,我会使用类似下面的merge,但我不确定它是否比你已经完成的更简单

merge(y,unique(x[,c('let','num'), with=FALSE]), all.x=TRUE, by='let')

答案 2 :(得分:2)

同意@David,很难简化。但是下面几个关键点: - )

setkey(x,let)
y<-x[!duplicated(let),.(let,num)][y]