我从这里、这里和这里的优秀资源中了解到,与依赖矢量扫描的相比,data.table利用自动索引(key即创建增压行名称)和基于二进制搜索的子集tidyverse。
我知道向量扫描需要扫描每一行并创建nrow(dataset)长度逻辑向量,而重复执行此操作效率不高。
我想知道是否有人可以帮助我准确地确定这两种方法如何意味着data.table与tidyverse需要按变量分组时相比,操作运行速度要快得多。即是否因为data.table自动索引group_by列并将其分解为分组的子集并对每个子集运行操作,而矢量扫描方法需要生成n = unique groups多个逻辑矢量,然后在整理结果之前对每个单独的逻辑矢量运行操作?
此外,根据data.table 小插图,
我们可以在多个列上设置键,并且列可以是不同的类型......
由于行被重新排序,一个 data.table 最多可以有一个键,因为它不能以多种方式排序。
我们可以在多列上设置键,而 adata.table最多只能有一个键,这意味着什么?即,在运行操作的任何时刻,是否只有一个引用键,但是当我们进行到整个操作的另一个组件时,引用键设置的哪一列可以更改?
先感谢您!
没有。
有多种方法可以找到组,然后按组计算表达式。每件事情都可以以不同的方式实现。它们与键或索引无关。也data.table不会在 group by 期间自动创建键/索引(截至目前)。
data.table 具有非常快速、精心实现的order功能,它被用于查找组。它后来被贡献给了基础 R。有一个想法可以在 dplyr 中使用它来加速分组:https : //github.com/tidyverse/dplyr/issues/4406
然而,从那时起 data.table 顺序功能得到了改进,现在扩展得更好。
除了寻找组,还有一部分是关于计算表达式的。如果我们评估“用户定义的函数”,它总是会慢得多。很多常用的函数都是内部优化过的,所以不会每组都在 R 和 C 之间切换。在这里,data.table 也非常仔细地实现了“GForce”功能。不确定,但在 dplyr 中,它们被称为“混合评估”。
对您的特定数据用例进行测试始终很重要。如果数据中只有 2 个独特的组,那么快速分组算法将不会大放异彩。
还有一个社区存储库,用于描述 data.table 算法https://github.com/asantucci/algo_data.table但它不是很活跃。我最近刚刚在那里发布了一条关于“groupby 优化”的评论,也将其粘贴在这里。答案由 data.table 作者 Matt Dowle 提供。
问:GForce 是否为最大组分配内存,然后复制组的值进行聚合,这样它可以从内存中连续受益,并且缓存效率更高?如果是这样,我们是否检查组是否尚未排序?所以我们可以避免做分配和复制?
A:
gforce(gsum) 一次分配给多个组结果;它不会将组聚集在一起。您正在描述复制到最大组的非 gforce (dogroup.c)。查看 dogroups.c 中的分支,它知道组是否已经分组:它切换到 memcpy。memcpy 非常快(连续,预取),所以它已经相当不错了。我们必须复制,因为 R 的 DATAPTR 不是我们可以重新指向的指针,它是 SEXP 的偏移量。