1.二级指标
a.什么是二级指标?
二级指标类似于key在data.table中的作用,但是两者主要有如下差别:
- 它不会对整个data.table进行排序,而是只对当列排序,并将此列存储在属性中index指标中。
- data.table中可以有多个二级指标
b.设置和得到二级指标
> setindex(flights, origin)
> head(flights)[,-c(1:6)]
arr_delay cancelled carrier tailnum flight origin dest air_time distance hour min
1: 13 0 AA N338AA 1 JFK LAX 359 2475 9 14
2: 13 0 AA N335AA 3 JFK LAX 363 2475 11 57
3: 9 0 AA N327AA 21 JFK LAX 351 2475 19 2
4: -26 0 AA N3EHAA 29 LGA PBI 157 1035 7 22
5: 1 0 AA N319AA 117 JFK LAX 350 2475 13 47
6: 0 0 AA N3DEAA 119 EWR LAX 339 2454 18 24
也可以使用: setindexv(flights, "origin") #在编程汇总,这种方法非常有用,第一种方法在交互模式下比较方便
> names(attributes(flights))
[1] "names" "row.names" "class" ".internal.selfref" "index"
- setindex()和setindexv()都能在data.table中添加二级指数
- 使用二级指标后,flights并没有进行升序排列,而key方法则会进行升序排列
- flights属性index中已经添加了“origin”
- setindex(flights,NULL)可以清除所有的二级指标
如何显示到目前为止flights所有的二级指标?
> indices(flights)
[1] "hour" "origin"
> setindex(flights, origin, dest)
> indices(flights)
[1] "hour" "origin" "origin__dest"
- 函数indices()返回目前为止filghts中所有的二级指标,如果没有,则返回NULL
- 设置新的二级指标,先前的二级指标并不会丢失,而是可以有多个二级指标
c)为什么我们需要二级指标?
考虑一个问题,假设我们需要设置一个主键“origin”,并寻找主键值等于“JFK”的所有行:
> setkey(flights, origin)
> flights["JFK"][,-c(1:6)] # or flights[.("JFK")]
setkey()存在的问题是:寻找匹配的行,其算法并不浪费时间,浪费时间的是对整个数据集进行排序的过程。如果再寻找另一个指标的值,则需要重新设置主键,排序并查找。我们需要的是不用重新排序,就能查找到所需的数据。
为什么是二级指标?因为二级指标可以设置多个,且已经存储在属性中index下,所以如果需要计算的话,可以直接调用,而不需要再重新对整个data.table进行升序排序。
新参数“on”拥有简洁的语法,并自动建立和使用二级指标。
on参数:
- 使用二级指标提取子集,可以快到飞起来,而且不必每次都设置setkey()
- 每次使用时,只需要检查属性下的index
- 语法简洁,可读性强,在key中,也建议使用on
2.on参数和二级指标在快速提取子集上的应用
a.在“j”上快速提取
在没有设置二级指标的情况下,
> flights["JFK", on = "origin"]
## alternatively
# flights[.("JFK"), on = "origin"] (or)
# flights[list("JFK"), on = "origin"]
此结果运行速度较慢,且观察数据结构如下:
> names(attributes(flights))
[1] "names" "row.names" "class" ".internal.selfref" "sorted"
> str(attributes(flights))
List of 5
$ names : chr [1:17] "year" "month" "day" "dep_time" ...
$ row.names : int [1:253316] 1 2 3 4 5 6 7 8 9 10 ...
$ class : chr [1:2] "data.table" "data.frame"
$ .internal.selfref:<externalptr>
$ sorted : chr "origin"
运行结果后,不会保存为属性index.此方法并不推荐
提前设置好二级指标,然后执行以下代码:
> setindex(flights, origin)
> flights["JFK", on = "origin", verbose = TRUE][1:5]
on= matches existing key, using key
Starting bmerge ...done in 0 secs
筛选两个匹配指标:
> flights[.("JFK", "LAX"), on = c("origin", "dest")][1:5]
year month day dep_time dep_delay arr_time arr_delay cancelled carrier tailnum flight origin dest air_time distance hour min
1: 2014 1 1 914 14 1238 13 0 AA N338AA 1 JFK LAX 359 2475 2: 2014 1 1 1157 -3 1523 13 0 AA N335AA 3 JFK LAX 363 2475 3: 2014 1 1 1902 2 2224 9 0 AA N327AA 21 JFK LAX 351 2475 4: 2014 1 1 1347 2 1706 1 0 AA N319AA 117 JFK LAX 350 2475 5: 2014 1 1 2133 -2 37 -18 0 AA N323AA 185 JFK LAX 338 2475
b.在“j”上进行选择
以下的操作与keys部分相似,唯一不同的多了参数“on”。原来是用key来限制的,现在是用on.
> flights[.("LGA", "TPA"), .(arr_delay), on = c("origin", "dest")]
arr_delay
1: 1
2: 14
3: -17
4: -4
5: -12
---
1848: 39
1849: -24
1850: -12
1851: 21
1852: -11
c.链接
排序
> flights[.("LGA", "TPA"), .(arr_delay), on = c("origin", "dest")][order(-arr_delay)]
arr_delay
1: 486
2: 380
3: 351
4: 318
5: 300
---
1848: -40
1849: -43
1850: -46
1851: -48
1852: -49
d. 在“j”上计算
计算最大值
> flights[.("LGA","TPA"),max(arr_delay),on=c("origin","dest")]
[1] 486
e. 替换
> flights[, sort(unique(hour))]
[1] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
> flights[.(23L), hour := 0L, on = "hour"]
> flights[, sort(unique(hour))]
[1] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
f. 用“by”分组汇总
> ans <- flights["JFK", max(dep_delay), keyby = month, on = "origin"]
> head(ans)
month V1
1: 1 881
2: 1 1014
3: 1 920
4: 1 1241
5: 1 853
6: 1 798
月份为什么都是1?
g. mult参数
> flights[c("BOS", "DAY"), on = "dest", mult = "first"]
year month day dep_time dep_delay arr_time arr_delay cancelled carrier tailnum flight origin dest air_time distance 1: 2014 1 1 1155 -5 1253 -11 0 B6 N368JB 2380 EWR BOS 45 200 2: 2014 1 1 1732 25 1945 35 0 EV N13968 3806 EWR DAY 102 533
> flights[.(c("LGA", "JFK", "EWR"), "XNA"), on = c("origin", "dest"), mult = "last"]
year month day dep_time dep_delay arr_time arr_delay cancelled carrier tailnum flight origin dest air_time distance 1: 2014 10 31 625 -5 829 -11 0 MQ N501MQ 3547 LGA XNA 165 1147
2: NA NA NA NA NA NA NA NA NA NA NA JFK XNA NA NA
3: 2014 10 31 634 -2 834 -25 0 EV N17138 4419 EWR XNA 160 1131
h. nomatch参数
> flights[.(c("LGA", "JFK", "EWR"), "XNA"), mult = "last", on = c("origin", "dest"), nomatch = 0L]
year month day dep_time dep_delay arr_time arr_delay cancelled carrier tailnum flight origin dest air_time distance
1: 2014 10 31 625 -5 829 -11 0 MQ N501MQ 3547 LGA XNA 165 1147
2: 2014 10 31 634 -2 834 -25 0 EV N17138 4419 EWR XNA 160 1131
3.自动添加指标
> set.seed(1L)
> dt = data.table(x = sample(1e5L, 1e7L, TRUE), y = runif(100L))
> print(object.size(dt), units = "Mb")
114.4 Mb
当我们第一次对某列使用“==”或“%in%”后,此列就会自动加入属性index中,
> names(attributes(dt))
[1] "names" "row.names" "class" ".internal.selfref"
> (t1 <- system.time(ans <- dt[x == 989L]))
用户 系统 流逝
0.56 0.06 0.72
> head(ans)
x y
1: 989 0.5372007
2: 989 0.5642786
3: 989 0.7151100
4: 989 0.3920405
5: 989 0.9547465
6: 989 0.2914710
> names(attributes(dt))
[1] "names" "row.names" "class" ".internal.selfref" "index"
> indices(dt)
[1] "x"
再一次进行查询上述语句,
> (t2 <- system.time(dt[x == 989L]))
用户 系统 流逝
> system.time(dt[x %in% 1989:2012])
用户 系统 流逝
0.00 0.00 0.07
原来是时间是0.72.现在是0.07,速度有了很大的提高。
如果不想自动添加二级指标,可以提前设置:options(datatable.auto.index = FALSE)
自动添加指标失效后,还可以用setindex()\setindexv()来设置,如果想全部禁用二级指标,可以设置:
options(datatable.use.index = FALSE)