【问题标题】:data.table: aggregate, join, and assign by referencedata.table:通过引用聚合、连接和分配
【发布时间】:2018-04-19 10:20:02
【问题描述】:

让我们将我要分配到的表称为 dta,并将我要加入和聚合到 dta 的数据的源称为 dts。

dta = data.table(i=1:4, x=rnorm(4))
dts = data.table(i=rep(1:3, each=3), z=runif(9))

我认为我应该能够加入“i”并在一个语句中对其进行汇总:

dta[dts, z_sum := sum(i.z), by=i, on='i']

可惜,这行不通

Error in `[.data.table`(dta, dts, `:=`(z_sum, sum(i.z)), by = i, on = "i") : 
  object 'i.z' not found

Enter a frame number, or 0 to exit   

1: dta[dts, `:=`(z_sum, sum(i.z)), by = i, on = "i"]
2: `[.data.table`(dta, dts, `:=`(z_sum, sum(i.z)), by = i, on = "i")

by=i 替换为by=.EACHI 会得到错误的结果(dtsz 的最后一个值是i 变量的每个值)

并且完全省略by 只是将所有值相加dts$z 并将相同的值分配给dta 中的所有行。

现在,我可以做到了:

dta[dts[, .(z=sum(z)), keyby=i], z := i.z, on='i']

但似乎应该有某种方式与 data.table 内部交互,以便在一个有效的语句中实现这一点,而不是单独的聚合,然后在这里完成连接。

我是否遗漏了什么,或者这是做事的最佳方式?我正在执行非常大的连接(将具有数亿行的表合并数千次),因此能够充分利用我所能达到的所有效率非常重要。

【问题讨论】:

  • 是的,这行得通,但这可能比我在上一个代码 sn-p 中概述的两步过程更有效吗?
  • 我猜它们都或多或少相同,只是你正在修改原始对象
  • 我猜当 dta 更大幅度地对 dts 进行子集化时,可以通过首先用 dta 对 dts 进行子集化,聚合,然后再加入,就像你所做的那样,可以避免一些计算。一个似乎有意义的例子。似乎有一个假设,即 i data.table 小于 x,这让我感到惊讶。感谢您的快速回复!

标签: r data.table split-apply-combine


【解决方案1】:

我们可以使用.EACHI

dta[, z_sum := dts[.SD, on = .(i), sum(z), by = .EACHI]$V1]

数据

set.seed(24)
dta = data.table(i=1:4, x=rnorm(4))
dts = data.table(i=rep(1:3, each=3), z=runif(9))

【讨论】:

  • 不,这对我来说不会产生正确的结果!正如我的帖子中提到的,它给了我每个 i 在 dts 中 z 的最后/第三个值,而不是 zs 的总和
  • @James 我认为dta[, sum_z3 := dts[dta, .(z=sum(z)), by=i, on=.(i)]$z] 有效,但最好还是有一个新功能
  • 我认为自己在 data.table 方面相当先进,但这对我来说似乎很神奇。你能解释一下步骤吗?
  • @RyanWard dta 中的.SD 是来自dta 的Data.table 的子集,我们在'dts' 的i 中使用它来通过'i1' 加入on .由于我们需要连接中每个“i”的“z”的sum,我们使用by
  • 谢谢。我想你是对的,这里的.SD 真的让我失望。
猜你喜欢
  • 2014-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-01
  • 1970-01-01
  • 2015-08-16
  • 2021-12-28
  • 1970-01-01
相关资源
最近更新 更多