【问题标题】:How to do a basic left outer join with data.table in R?如何在 R 中使用 data.table 进行基本的左外连接?
【发布时间】:2011-10-28 18:29:35
【问题描述】:

我有一个 a 和 b 的 data.table,我已将其划分为 below,b above,b > .5:

DT = data.table(a=as.integer(c(1,1,2,2,3,3)), b=c(0,0,0,1,1,1))
above = DT[DT$b > .5]
below = DT[DT$b < .5, list(a=a)]

我想在above 和below 之间进行左外连接:对于above 中的每个a,计算below 中的行数。这相当于 SQL 中的以下内容:

with dt as (select 1 as a, 0 as b union select 1, 0 union select 2, 0 union select 2, 1 union select 3, 1 union select 3, 1),
  above as (select a, b from dt where b > .5),
  below as (select a, b from dt where b < .5)
select above.a, count(below.a) from above left outer join below on (above.a = below.a) group by above.a;
 a | count 
---+-------
 3 |     0
 2 |     1
(2 rows)

如何使用 data.tables 完成相同的任务?这是我迄今为止尝试过的:

> key(below) = 'a'
> below[above, list(count=length(b))]
     a count
[1,] 2     1
[2,] 3     1
[3,] 3     1
> below[above, list(count=length(b)), by=a]
Error in eval(expr, envir, enclos) : object 'b' not found
> below[, list(count=length(a)), by=a][above]
     a count b
[1,] 2     1 1
[2,] 3    NA 1
[3,] 3    NA 1

我还应该更具体一点,因为我已经尝试过merge,但这会破坏我系统上的内存(并且数据集只占用我大约 20% 的内存)。

【问题讨论】:

  • 你能用人类的语言写下你想要达到的目标吗?
  • 您可以先尝试寻找答案。 data.table 是 data.frame 的扩展,具有合并功能。
  • 同意你应该用自然语言解释你想要什么,但另外我在版本 1.6 和(更新后)1.6.4 中都得到一个错误:abs(j) 中的错误:非数字参数到数学函数此外:警告消息:在 is.na(j) 中:is.na() 应用于“NULL”类型的非(列表或向量)
  • 抱歉,来晚了——希望这个问题现在好很多倍。

标签: sql r data.table


【解决方案1】:

看看这是否给你一些有用的东西。您的示例太稀疏,无法让我知道您想要什么,但似乎它可能是 above$a 的值的列表,这些值也在 below$a 中

table(above$a[above$a %in% below$a])

如果您还想要 converse ... 值不在 below 中,那么可以这样做:

table(above$a[!above$a %in% below$a])

您可以将它们连接起来:

> c(table(above$a[above$a %in% below$a]),table(above$a[!above$a %in% below$a]) )
2 3 
1 2

通常table 和%in% 运行在相当小的空间内并且速度很快。

【讨论】:

  • 不过,这并没有给我计数为 0 的 as,这就是我想要左外连接的原因。
  • 是的。 “零计数”是 !x %in% y 索引中的 2 个“3”。如果你想给它们贴上这样的标签,你可以在它们之间插入一个额外的命名值:zeros-&gt;=0,
【解决方案2】:

由于您似乎正在使用包data.table:请检查?merge.data.table。 我没有使用它,但它似乎可以满足您的需求:

merge(above, below, by="a", all.x=TRUE, all.y=FALSE)

【讨论】:

  • 事实上合并是基本功能,也适用于data.frames。
  • @mbq: merge.data.table 和merge.data.frame 真的很不一样。
  • @DWin 好的,但是不需要 data.tables 来获得合并功能。
  • @mbq。这是正确的......但是如果一个人正在使用 data.table 对象,那么一个人确实需要知道正确的语法来实现自己的目标,并且只能从 ?merge.data.table 而不是 ?merge.data.frame 收集.
  • 在 by 列唯一有效的情况下有效,但在左连接中并非总是如此
【解决方案3】:

我认为这更容易:

setkey(above,a)
setkey(below,a)

左外连接:

above[below, .N]

常规加入:

above[below, .N, nomatch=0]

带计数的完全外连接:

merge(above,below, all=T)[,.N, by=a]

【讨论】:

  • 不会因为.Nabove[below, .N] 只返回总行数吗?
【解决方案4】:

我最终找到了一种使用 data.table 的方法,我觉得这比 DWin 的 table 更自然,尽管 YMMV:

result = below[, list(count=length(b)), by=a]
key(result) = 'a'
result = result[J(unique(above$a))]
result$count[is.na(result$count)] = 0

不过,我不知道这是否可以更紧凑。我特别希望能够做类似result = below[J(unique(above$a)), list(count=length(b))] 的事情,但这不起作用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-13
    • 2019-07-29
    • 2012-11-09
    • 2011-11-13
    • 2016-04-08
    相关资源
    最近更新 更多