R 在data.table中设置键的目的是什么?
我正在使用data.table,有许多函数需要我设置一个键(例如R 在data.table中设置键的目的是什么?,r,data.table,R,Data.table,我正在使用data.table,有许多函数需要我设置一个键(例如X[Y])。因此,我希望了解为了在数据表中正确设置键,键是做什么的 我读到的一个来源是?setkey setkey()对数据表进行排序,并将其标记为已排序。已排序的列是键。键可以是任意顺序的任意列。列始终按升序排序。该表通过引用进行了更改。除了一列大小的临时工作内存外,根本不复制 我在这里的收获是,一个键将对data.table进行“排序”,从而产生与order()非常相似的效果。然而,它并没有解释拥有钥匙的目的 data.ta
X[Y]
)。因此,我希望了解为了在数据表中正确设置键,键是做什么的
我读到的一个来源是
?setkey
setkey()
对数据表进行排序,并将其标记为已排序。已排序的列是键。键可以是任意顺序的任意列。列始终按升序排序。该表通过引用进行了更改。除了一列大小的临时工作内存外,根本不复制
我在这里的收获是,一个键将对data.table进行“排序”,从而产生与order()
非常相似的效果。然而,它并没有解释拥有钥匙的目的
data.table FAQ 3.2和3.3解释了:
3.2我没有一个大表上的键,但是分组仍然非常快。为什么呢
data.table使用基数排序。这比其他的要快得多
排序算法。基数仅适用于整数,请参见
?base::sort.list(x,method=“基数”)
。这也是原因之一
setkey()
很快。当没有设置关键点,或者我们以不同的顺序分组时
从密钥的角度来看,我们称之为“临时用户”
3.3为什么按键中的列进行分组比按特殊列进行分组快
因为每个组在RAM中是连续的,所以最小化了页面
获取,并且可以批量复制内存(memcpy
在C中),而不是
在C中循环
从这里开始,我猜设置一个键可以让R在某种程度上使用“基数排序”而不是其他算法,这就是为什么它更快的原因
《10分钟快速入门指南》中还提供了有关关键点的指南
钥匙
让我们首先考虑data.frame,特别是行名(或
英文,行名称)。也就是说,多个名称属于一个
一行属于同一行的多个名称?那不是什么
我们习惯于在data.frame中使用。我们知道每行最多有一个
名称一个人至少有两个名字,第一个名字和第二个名字。
这对于组织电话簿很有用,例如
按姓氏排序,然后按rst名称排序。但是,一行中的每一行
data.frame只能有一个名称
钥匙由一个或多个部件组成
行名称的列,可以是整数、因子、字符或某些
其他类,而不仅仅是字符。此外,行是按
钥匙。因此,data.table最多只能有一个键,因为它
不能以多种方式排序
不强制执行唯一性,
i、 例如,允许重复的键值。因为行是按
键,键中的任何重复项都将连续出现
电话簿有助于理解键是什么,但似乎键与“因子”列没有区别。此外,它没有解释为什么需要键(特别是使用某些函数)以及如何选择要设置为键的列。此外,在以时间为列的data.table中,将任何其他列设置为键可能也会弄乱时间列,这使得它更加混乱,因为我不知道是否允许将任何其他列设置为键。有人能告诉我吗?键基本上是数据集的索引,它允许非常快速有效的排序、筛选和联接操作。这些可能是使用数据表而不是数据帧的最佳理由(使用数据表的语法也更加用户友好,但这与键无关)
如果你不理解索引,考虑一下:电话簿是按名称“索引”的。所以,如果我想查找某人的电话号码,这很简单。但假设我想按电话号码搜索(例如,查找谁有特定的电话号码)?除非我能通过电话号码“重新索引”电话簿,否则这将需要很长时间
考虑以下示例:假设我有一个表ZIP,其中包含美国所有邮政编码(>33000)以及相关信息(城市、州、人口、收入中值等)。如果我想查找特定邮政编码的信息,如果我先setkey(zip,zipcode)
,搜索(过滤器)的速度大约会快1000倍
另一个好处与连接有关。假设a在数据表中有一个人员列表和他们的邮政编码(称之为“PPL”),我想从邮政编码表中附加信息(例如城市、州等)。以下代码将执行此操作:
setkey(ZIP,zipcode)
setkey(PPL,zipcode)
full.info <- PPL[ZIP, nomatch=F]
setkey(ZIP,zipcode)
设置键(PPL,zipcode)
full.info次要更新:请同时参阅。重点介绍我们计划讨论的其他小插曲
我再次更新了这个答案(2016年2月),因为新的on=
功能也允许临时连接。有关早期(过时)答案,请参阅历史记录
setkey(DT,a,b)
?
它做两件事:
按引用提供的列(a、b)对data.tableDT
的行重新排序,始终按递增顺序排列
通过将名为sorted
的属性设置为DT
,将这些列标记为键列
重新排序既快(由于data.table的内部基数排序),又节省内存(只分配了一个double类型的额外列)
何时需要setkey()
?
对于分组操作,setkey()
从来不是绝对的要求。也就是说,我们可以通过或临时通过进行感冒治疗
请注意,on=
参数也可以显式指定,即使对于键控的联接也是如此
唯一需要绝对设置键
的操作是功能。但我们正在开发更多的功能,这些功能完成后将删除此要求
- 那么实现
o的原因是什么
## "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
## 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")]
## 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")]