我使用的是data.table,有许多功能需要我设置一个键(例如X[Y]).因此,我希望了解一个键是如何在我的数据表中正确设置键的.


我读到的一个消息来源是?setkey.

setkey()data.table进行排序,并将其标记为已排序.排序的列是关键.键可以是任意顺序的任意列.列始终按升序排序.该表因引用而更改.除了一列大小的临时工作内存外,根本不复制任何内容.

我在这里的收获是,一个键可以"排序"数据.表,产生与order()非常相似的效果.然而,这并不能解释拥有 keys 的目的.


数据.表FAQ 3.2和3.3解释了:

3.2我没有大桌子上的 keys ,但分组仍然非常快.为什么?

数据表使用基数排序.这比其他方法快得多

3.3为什么按键中的列进行分组比按特殊列进行分组更快?

因 for each 组在RAM中是连续的,因此最小化了页面

从这里开始,我猜设置一个键在某种程度上允许R使用"基数排序"而不是其他算法,这就是为什么它更快的原因.


《10分钟快速入门指南》中还有一个关于关键点的指南.

  1. keys

让我们从考虑数据开始.框架,特别是行名(或

keys 由一个或多个部件组成

唯一性不被强制执行,

电话簿有助于理解键是什么,但键与因子列相比似乎没有什么不同.此外,它没有解释为什么需要键(尤其是使用某些函数)以及如何 Select 要设置为键的列.而且,似乎在一个数据时代.以时间为列的表,将任何其他列设置为键可能也会弄乱时间列,这使得它更加混乱,因为我不知道是否允许将任何其他列设置为键.有人能告诉我吗?

推荐答案

除了这个答案,还请参考插图Secondary indices and auto indexingKeys and fast binary search based subset.

This issue重点介绍了我们计划进行的其他小插曲.


我再次更新了这个答案(2016年2月),因为新的on=功能允许ad-hoc次加入.请参阅历史记录以了解早期(过时的)答案.

What exactly does setkey(DT, a, b) do?

它有两个功能:

  1. 按照(ab)by reference提供的列对data.table DT中的行重新排序,始终按increasing顺序排列.
  2. 通过将名为sorted的属性设置为DT,将这些列标记为key列.

重新排序既快(由于data.table的内部基数排序),又节省内存(只分配了一个double类型的额外列).

When is setkey() required?

对于分组操作,setkey()从来不是绝对的要求.也就是说,我们可以执行cold-byadhoc-by.

## "cold" by
require(data.table)
DT <- data.table(x=rep(1:5, each=2), y=1:10)
DT[, mean(y), by=x] # no key is set, order of groups preserved in result

然而,在v1.9.6之前,表格x[i]的连接要求将key设置为x.With the new 104 argument from v1.9.6+,这不再是真的了,因此在这里设置按键也是绝对的要求.

## joins using < v1.9.6 
setkey(X, a) # absolutely required
setkey(Y, a) # not absolutely required as long as 'a' is the first column
X[Y]

## joins using v1.9.6+
X[Y, on="a"]
# or if the column names are x_a and y_a respectively
X[Y, on=c("x_a" = "y_a")]

请注意,即使对于keyed个连接,也可以显式指定on=个参数.

唯一需要绝对设置key的操作是foverlaps()函数.但我们正在开发更多的功能,完成后将删除此要求.

  • So what's the reason for implementing 100 argument?

    原因有很多.

    1. 它可以清楚地将该操作区分为涉及两个data.tables的操作.仅仅做X[Y]也不能区分这一点,尽管可以通过适当地命名变量来明确这一点.

    2. 它还允许通过查看该行代码(而不必回溯到对应的setkey()行)来理解join/subset正在立即执行的列.

    3. 在不需要更新整个操作或更多操作的by reference列中添加数据.仅为添加/更新列而重新排序的表.例如

       ## compare 
       setkey(X, a, b) # why physically reorder X to just add/update a column?
       X[Y, col := i.val]
      
       ## to
       X[Y, col := i.val, on=c("a", "b")]
      

      在第二种情况下,我们不需要重新订购.耗时的不是计算顺序,而是对数据进行物理重新排序.在RAM中,通过避免它,我们保留了原来的顺序,而且它也是性能良好的.

    4. 否则,除非重复执行联接,否则keyedad-hoc联接之间应该没有明显的性能差异.

这就引出了一个问题:输入data.table还有什么优势?

  • Is there an advantage to keying a data.table?

    键入data.table会根据RAM中的这些列对其进行物理重新排序.计算顺序通常不是耗时的部分,而是reordering本身.然而,一旦我们在RAM中对数据进行了排序,属于同一组的行在RAM中都是连续的,因此缓存效率非常高.正是这种分类能力加快了对关键数据的操作.桌子.

    因此,有必要弄清楚是否需要花费时间对整个数据进行重新排序.表值得花时间进行缓存高效的连接/聚合.通常情况下,除非对相同的keyed个数据执行重复的分组/联接操作.表中,应该没有明显的差异.

因此,在大多数情况下,不需要再设置关键点.我们建议尽可能使用on=,除非设置键在性能上有显著提高,您希望利用这一点.

Question:如果使用setorder()data.table进行重新排序,使用on=,那么与keyed连接相比,您认为性能会如何?如果到目前为止您已经了解了,您应该能够弄清楚:-).

R相关问答推荐

将收件箱变量传递给ggplot 2函数

使用sensemakr和fixest feols模型(R)

计算R中的威布尔分布的EDF

如何 bootstrap glm回归、估计95%置信区间并绘制它?

从gtsummary包中使用tBL_strata()和tBL_summary()时删除变量标签

如果行和大于值,则过滤

有没有一个R函数允许你从一个数字变量中提取一个数字,而不考虑它的位置(不仅仅是第一个或最后一个数字?

筛选出以特定顺序患病的个体

在df中保留原始变量和新变量

如何从像glm这样的模型中提取系数表的相关性?

派生程序包| ;无法检索';return()';的正文

如何从向量构造一系列双边公式

提高圣彼得堡模拟的速度

手动指定从相同数据创建的叠加图的 colored颜色

循环遍历多个变量,并将每个变量插入函数R

`-`是否也用于数据帧,有时使用引用调用?

网络抓取新闻标题和时间

整理曲线图、曲线图和点图

按镜像列值自定义行顺序

抽样变换-REXP与RWEIBUR