【问题标题】:setkey and the := operator, data.table, Rsetkey 和 := 运算符、data.table、R
【发布时间】:2025-12-01 21:15:01
【问题描述】:

使用data.table 包时,我有点不确定何时需要setkey()。例如,当使用:= 运算符和by 选项时,即使我没有设置密钥,事情似乎仍然非常快。有人可以说明何时需要setkey(),何时不需要?如果在使用by 调用:= 之前没有必要,那么data.table 包怎么这么快,因为它可能必须通过执行顺序搜索来做与标准data.frame R 中的apply 相同的事情而不是二进制的,因为它不知道我的data.table 是否实际上是按by 的参数排序的。

谢谢

【问题讨论】:

    标签: r dataframe data.table apply


    【解决方案1】:

    这两个常见问题似乎很接近:

    3.2 我没有大桌子上的钥匙,但是分组还是很快的。为什么会这样?
    data.table 使用基数排序。这比其他排序算法快得多。 Radix 仅适用于整数,请参阅?base::sort.list(x,method="radix")。这也是setkey快的原因之一。当没有设置键,或者我们以与键不同的顺序分组时,我们称其为 ad hoc by。

    3.3 为什么按 key 中的列分组比 ad hoc by 更快?
    因为每个组在 RAM 中是连续的,从而最大限度地减少页面获取,并且可以批量复制内存(C 中的memcpy)而不是 C 中的循环。

    在您注意到 keyed by 和 ad hoc by 之间的区别之前,它没有说并且可能应该做的是,您需要一个非常大的数据集,其中每个组也非常大。类似于 100 组,每组 100MB(一个 10GB 的 data.table),例如 1e8 行和 13 列。否则,没有必要先setkey,尤其是因为这会很麻烦。

    【讨论】:

    • 太棒了,谢谢!正在研究常见问题解答,一定错过了。
    • ad hoc by 是否很快,因为它也使用基数排序?
    • @colinfang 很难回答这个问题,因为它涉及到几个功能。原因因查询和数据而异。 Ad hoc by 确实使用基数排序来查找整数列的组,因此它取决于类型和有多少列被“by”-ed。然后,一旦它找到了组,分组速度很快的一个原因是因为预先为最大的组分配了内存,然后再为所有组重用。并且仅适用于j 所需的列。请参阅常见问题解答 3.1。尝试verbose=TRUE 模式,因为它揭示了查找组(包括基数排序)与迭代它们所花费的时间。