【问题标题】:left outer join with data.table with different names for key variables与 data.table 的左外连接,键变量的名称不同
【发布时间】:2016-01-06 23:19:38
【问题描述】:

首先让我说这是我在堆栈溢出上发布的第一个问题。如果我需要更改问题中的样式、格式等,请告诉我。

我想对两个数据表执行左外连接操作,但条件是允许我为两个数据表中的关键变量使用不同的名称。示例:

DT1 = data.table(x1=c("b","c", "a", "b", "a", "b"),   x2a=1:6,m1=seq(10,60,by=10))
setkey(DT1,x1,x2a)
> DT1
   x1 x2a m1
1:  a   3 30
2:  a   5 50
3:  b   1 10
4:  b   4 40
5:  b   6 60
6:  c   2 20
DT2 = data.table(x1=c("b","d", "c", "b","a","a"),x2b=c(1,4,7,6," "," "),m2=5:10)
setkey(DT2,x1,x2b)
> DT2
   x1 x2b m2
1:  a      9
2:  a     10
3:  b   1  5
4:  b   6  8
5:  c   7  7
6:  d   4  6
############# first, I use the merge operation on the data frames to do a left outer join
dfL<-merge.data.frame(DT1,DT2,by.x=c('x1','x2a'),by.y=c('x1','x2b'),all.x=TRUE)
> dfL
  x1 x2a m1 m2
1  a   3 30 NA
2  a   5 50 NA
3  b   1 10  5
4  b   4 40 NA
5  b   6 60  8
6  c   2 20 NA
################# attempt with data table left outer join 
> dtL<-DT2[DT1,on=c("x1","x2a")]
Error in forderv(x, by = rightcols) : 
  'by' value -2147483648 out of range [1,3]

#################### code that works with data table
DT1 = data.table(x1=c("b","c", "a", "b", "a", "b"), x2=as.character(1:6),m1=seq(10,60,by=10))
setkey(DT1,x1,x2)
DT1
DT2 = data.table(x1=c("b","d", "c", "b","a","a"),x2=c(1,4,7,6," "," ") ,m2=5:10)
setkey(DT2,x1,x2)
DT2
dtL<-DT2[DT1]
######################## this required identical naming of the key variables in the two data tables
################### Also does not allow a ad-hoc selection of the key variables with the "on" argument

我想知道是否可以保留合并命令与数据框的灵活性。使用 data.table。

【问题讨论】:

  • 加载了data.table,您可以使用merge() 语法并指定连接列,而无需设置键。见?data.table::merge
  • library(data.table); merge(DT1, DT2, by.x=c('x1','x2a'), by.y=c('x1','x2b'), all.x=TRUE)

标签: r data.table


【解决方案1】:

从 v1.9.6 开始(CRAN 2015 年 9 月):

X[Y] 语法现在可以加入,而无需设置键 使用新的on 参数。例如:DT1[DT2, on=c(x = "y")] 将 将DT2 的“y”列与DT1 的“x”连接起来。 DT1[DT2, on="y"] 将连接两个 data.tables 的“y”列。

请在README 中搜索字符串“on=”以获取与开发中的 v1.9.7 中的on= 相关的更多项目。您要求使用左外连接,这是 X[Y] 语法的默认设置(X[Y,nomatch=0] 切换到内连接)。

但请注意,如果您可以支付setkey 的前期费用(在 data.table 中非常快),那么设置密钥总是会更快地随后加入。这个概念类似于 SQL 中的聚集索引。

X[Y] 语法与merge() 相比的优势在于,您可以在同一个[...] 查询中包含jby。这样的查询经过优化,因此只有 j 表达式所需的列被连接,从而节省时间和 RAM。请参阅常见问题解答 1.12。 by=.EACHI 也是 X[Y] 语法的一个强大功能,而 merge() 目前是 data.table 独有的。您可以在 DT[...] 查询中使用 on=by=.EACHI

【讨论】:

  • 是否有 html 版本的常见问题解答,还是仅提供 .pdf (as linked here in support > Links)?
  • 见 FAQ 6.10 :-) 它也在CRAN page
  • 哈哈——够公平的。我还在思考常见问题解答 1.12,所以还没有那么远:)
  • @Matt Dowle 我收到 rtL2 的错误消息
  • @Vivek 请提出一个新问题,如果它在Support 中的步骤中幸存下来;例如按照第 6 点在链接部分下包含错误消息和第 4 点。
【解决方案2】:

来自?data.table::merge

data.table 的这种合并方法与 data.frames 的行为非常相似,但有一个主要例外:默认情况下,用于合并 data.tables 的列是共享键列,而不是同名的共享列.显式设置 by 或 by.x、by.y 参数以覆盖此默认值。

所以我们可以使用by 参数来覆盖keys

library(data.table)

DT1 = data.table(x1=c("b","c", "a", "b", "a", "b"),   x2a=1:6,m1=seq(10,60,by=10))
DT2 = data.table(x1=c("b","d", "c", "b","a","a"),x2b=c(1,4,7,6," "," "),m2=5:10)

## you will get an error when joining a character to a integer:
DT2$x2b <- as.integer(DT2$x2b)
## Alternative:
## DT2 = data.table(x1=c("b","d", "c", "b","a","a"),x2b=c(1,4,7,6,NA,NA),m2=5:10)

merge(DT1, DT2, by.x=c('x1','x2a'), by.y=c('x1','x2b'), all.x=TRUE)

   x1 x2a m1 m2
1:  a   3 30 NA
2:  a   5 50 NA
3:  b   1 10  5
4:  b   4 40 NA
5:  b   6 60  8
6:  c   2 20 NA

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    相关资源
    最近更新 更多