R中的data.table
包提供了一个data.frame
的高级版本,让你的程序作数据整型的运算速度大大的增长。data.table
已经在金融,基因工程学等领域大放光彩。他尤为适合那些须要处理大型数据集(好比 1GB 到100GB)须要在内存中处理数据的人。不过这个包的一些符号并非很容易掌握,由于这些操做方式在R中比较少见。这也是这篇文章的目的,为了给你们提供一个速查的手册。php
data.table
的通用格式: DT[i, j, by],对于数据集DT,选取子集行i,经过by分组计算jcss
生成一个data.table对象,记为DT.html
> library(data.table) > set.seed(45L) > DT <- data.table(V1=c(1L,2L), + V2=LETTERS[1:3], + V3=round(rnorm(4),4), + V4=1:12) > DT V1 V2 V3 V4 1: 1 A -1.1727 1 2: 2 B -0.3825 2 3: 1 C -1.0604 3 4: 2 A 0.6651 4 5: 1 B -1.1727 5 6: 2 C -0.3825 6 7: 1 A -1.0604 7 8: 2 B 0.6651 8 9: 1 C -1.1727 9 10: 2 A -0.3825 10 11: 1 B -1.0604 11 12: 2 C 0.6651 12
选取第三行到第五行git
> DT[3:5,] #or DT[3:5] V1 V2 V3 V4 1: 1 C -1.0604 3 2: 2 A 0.6651 4 3: 1 B -1.1727 5
在V2这一列,选择全部值为A的行github
> DT[ V2 == "A"]
V1 V2 V3 V4
1: 1 A -1.1727 1 2: 2 A 0.6651 4 3: 1 A -1.0604 7 4: 2 A -0.3825 10
选择在这一列中包含value1或value2的全部值spring
> DT[column %in% c("value1","value2")]
选择V2这列中包含值A或C的全部行sql
> DT[ V2 %in% c("A","C")] V1 V2 V3 V4 1: 1 A 0.3408 1 2: 2 A -0.7460 4 3: 1 A -0.3795 7 4: 2 A -0.7033 10 5: 1 C -0.3795 3 6: 2 C -0.7033 6 7: 1 C 0.3408 9 8: 2 C -0.7460 12
> DT[,V2]
[1]"A" "A" "A" "A" "B" "B" "B" "B" "C" "C" "C" "C"
注意到V2这一列是以向量的形式返回的json
> DT[,.(V2,V3)] V2 V3 1: A 0.3408 2: A -0.7460 3: A -0.3795 4: A -0.7033 5: B -0.7033 6: B 0.3408 7: B -0.7460 8: B -0.3795 9: C -0.3795 10: C -0.7033 11: C 0.3408 12: C -0.7460
V2与V3这两列以data.table的形式返回ruby
.()为list()的一个别名。若是使用.(),返回的为一个data.table对象。若是不使用.(),结果为返回一个向量。markdown
> DT[,sum(V1)] [1] 18
以向量的形式返回V1列中全部元素的总和
以data.table的形式,返回V1这列的全部元素之和与V3这列的标准差
> DT[,.(sum(V1),sd(V3))] V1 V2 1: 18 0.4546055
相似上例,但有一个新的列名
> DT[,.(Aggregate = sum(V1), Sd.V3 = sd(V3))] Aggregate Sd.V3 1: 18 0.4546055
选择V1这一列,并计算V3这列的标准差,将会获得一个标准差的值并循环补齐
> DT[,.(V1, Sd.V3 = sd(V3))] V1 Sd.V3 1: 1 0.4546055 2: 2 0.4546055 3: 1 0.4546055 4: 2 0.4546055 5: 2 0.4546055 6: 1 0.4546055 7: 2 0.4546055 8: 1 0.4546055 9: 1 0.4546055 10: 2 0.4546055 11: 1 0.4546055 12: 2 0.4546055
输出V2这一列并绘制V3这一列
> DT[,{print(V2)
plot(V3)
NULL}] [1] "A" "A" "A" "A" "B" "B" "B" "B" "C" "C" "C" "C" #And a plot NULL
对V1中的每一类来计算V4列的和
> DT[,.(V4.Sum = sum(V4)),by=V1]
V1 V4.Sum
1: 1 36 2: 2 42
与上例相似,但每个分组包含V1和V2两列
> DT[,.(V4.Sum = sum(V4)),by=.(V1,V2)]
V1 V2 V4.Sum
1: 1 A 8 2: 2 A 14 3: 2 B 10 4: 1 B 16 5: 1 C 12 6: 2 C 18
以sign(V1-1)为分组,计算各个分组中V4列的和:
> DT[,.(V4.Sum = sum(V4)),by=sign(V1-1)] sign V4.Sum 1: 0 36 2: 1 42
在前5行数据集中,经过V1列的分组来计算V4列的总和:
> DT[1:5,.(V4.Sum = sum(V4)),by=V1] V1 V4.Sum 1: 1 8 2: 2 16
在V1列中计算每一个分组的观测数
> DT[,.N,by=V1]
V1 N
1: 1 6 2: 2 6
注意: 额外的指定 (DT <- DT[…])是多余的
使用:=来更新V1列:
> DT[, V1 := round(exp(V1),2)]
这段代码没有显式的返回结果,而V1列从[1] 1 2 1 2 … 变成了 [1] 2.72 7.39 2.72 7.39 …
使用:=更新V1列和V2列:
> DT[, c("V1","V2") := list(round(exp(V1),2), LETTERS[4:6])]
一样没有显式的返回结果,V1列的结果与上相同,V2列从[1] “A” “B” “C” “A” “B” “C” … 变成: [1] “D” “E” “F” “D” “E” “F” …
上例的另外一种写法,但会在书写时更易并齐。并且,当添加[]时,结果会返回在屏幕中
> DT[, ':=' (V1 =round(exp(V1),2),V2 = LETTERS[4:6])][]
与上例变化相同,可是因为在语句最后添加了[],这一结果会返回至屏幕
移除V1列
> DT[, V1 := NULL]
无显式的返回结果,但V1列变为NULL
移除V1列与V2列
> DT[, c("V1","V2") := NULL]
无显式的返回结果,但V1列与V2列变为NULL
将一个包含列名的变量用小括号包裹起来,变量所传递的内容将会被删除
注意:列名为Cols.chosen的列将会被删除,这里不是删除”V1”,”V2”列
> Cols.chosen = c("V1","V2") > DT[, Cols.chosen := NULL]
无显式的返回结果,列名为Cols.chosen的列将会被删除
删除指定变量Cols.chosen包含的V1列和V2列
> DT[, (Cols.chosen) := NULL]
无显式的返回结果,列名为V1和V2的列变为NULL##索引与键值
setkey()函数能够在数据集DT上设置键值。当咱们设置好key后,data.table会将数据按照key来排序。
在V2列上设置一个键值
> setkey(DT,V2)
无显示返回结果
使用键值能够更加有效地选择行
因为已将V2设置了键值,将会返回该列中全部包含变量值A的行
> DT["A"]
V1 V2 V3 V4
1: 1 A -1.1727 1 2: 2 A 0.6651 4 3: 1 A -1.0604 7 4: 2 A -0.3825 10
返回键值所在列(V2列)包含变量值A或变量值C的全部行
> DT[c("A","C")] V1 V2 V3 V4 1: 1 A -0.8981 1 2: 2 A -0.1745 4 3: 1 A -0.5014 7 4: 2 A -0.3348 10 5: 1 C -0.5014 3 6: 2 C -0.3348 6 7: 1 C -0.8981 9 8: 2 C -0.1745 12
mult参数是用来控制i匹配到的哪一行的返回结果默认状况下会返回该分组的全部元素
返回匹配到键值所在列(V2列)全部行中的第一行
> DT["A", mult ="first"] V1 V2 V3 V4 1: 1 A -1.1727 1
返回匹配到键值所在列(V2列)全部行中的最后一行
> DT["A", mult = "last"] V1 V2 V3 V4 1: 2 A -0.3825 10
nomatch参数用于控制,当在i中没有到匹配数据的返回结果,默认为NA,也能设定为0。0意味着对于没有匹配到的行将不会返回。
返回匹配到键值所在列(V2列)全部包含变量值A或D的全部行:
> DT[c("A","D")] V1 V2 V3 V4 1: 1 A -1.1727 1 2: 2 A 0.6651 4 3: 1 A -1.0604 7 4: 2 A -0.3825 10 5: NA D NA NA
变量值A匹配到了,而变量值D没有,故返回NA。
返回匹配到键值所在列(V2列)全部包含值A或D的全部行:
> DT[c("A","D"), nomatch = 0] V1 V2 V3 V4 1: 1 A -1.1727 1 2: 2 A 0.6651 4 3: 1 A -1.0604 7 4: 2 A -0.3825 10
由于nomatch参数,值D没有匹配到故不返回。
by=.EACHI
容许按每个已知i的子集分组,在使用by=.EACHI时须要设置键值
返回键值(V2列)中包含A或C的全部行中,V4列的总和。
> DT[c("A","C"), sum(V4)] [1] 52
返回键值所在列(V2列)中包含A的行在V4列总和与包含C的行在V4列的总和。
> DT[c("A","C"), sum(V4), by=.EACHI] V2 V1 1: A 22 2: C 30
任意列都能使用setkey()来设置主键,这种方式能够选择2个列做为一个主键。如下是一个等值链接V1列的每一个组先根据V1排序,再根据V2排序。
> setkey(DT,V1,V2)
无显式返回结果
选择键值1(V1列)为2且键值2(V2列)为C的行。
> DT[.(2,"C")] V1 V2 V3 V4 1: 2 C -0.3825 6 2: 2 C 0.6651 12
选择键值1(V1列)为2且键值2(V2列)为A或C的行
> DT[.(2,c("A","C"))] V1 V2 V3 V4 1: 2 A 0.6651 4 2: 2 A -0.3825 10 3: 2 C -0.3825 6 4: 2 C 0.6651 12
.N能够用来表示行的数量或者最后一行
在i处使用:
> DT[.N-1] V1 V2 V3 V4 1: 1 B -0.5765 11
返回每一列的倒数第二行
在j处使用:
> DT[,.N-1] [1] 11
返回倒数第二行所在的行数。
.()
是list()
的一个别名,他们在data.table中是等价的。当只有一个元素的位置j或者by中,是不须要.()
的。
在j中使用:
> DT[,.(V2,V3)] #or DT[,list(V2,V3)] V2 V3 1: A -0.8313 2: B 0.7615 3: C -0.5765
在by中使用:
> DT[, mean(V3),by=.(V1,V2)]
V1 V2 V1
1: 1 A -0.70390 2: 2 B 0.06755 3: 1 C -0.70390 4: 2 A 0.06755 5: 1 B -0.70390 6: 2 C 0.06755
以V1,V2为分组,对V3求均值
.SD
是一个data.table,他包含了各个分组,除了by中的变量的全部元素。.SD
只能在位置j中使用:
> DT[, print(.SD), by=V2] V1 V3 V4 1: 1 -0.8313 1 2: 2 -0.6264 4 3: 1 -0.5765 7 4: 2 0.7615 10 V1 V3 V4 1: 2 0.7615 2 2: 1 -0.8313 5 3: 2 -0.6264 8 4: 1 -0.5765 11 V1 V3 V4 1: 1 -0.5765 3 2: 2 0.7615 6 3: 1 -0.8313 9 4: 2 -0.6264 12 Empty data.table (0 rows) of 1 col: V2
以V2为分组,选择每组的第一和最后一列:
> DT[,.SD[c(1,.N)], by=V2] V2 V1 V3 V4 1: A 1 -0.8313 1 2: A 2 0.7615 10 3: B 2 0.7615 2 4: B 1 -0.5765 11 5: C 1 -0.5765 3 6: C 2 -0.6264 12
以V2为分组,计算.SD
中全部元素的和:
> DT[, lapply(.SD, sum), by=V2]
V2 V1 V3 V4
1: A 6 -1.2727 22 2: B 6 -1.2727 26 3: C 6 -1.2727 30
.SDcols
常于.SD
用在一块儿,他能够指定.SD
中所包含的列,也就是对.SD
取子集:
> DT[, lapply(.SD,sum), by=V2,
+ .SDcols = c("V3","V4")] V2 V3 V4 1: A -1.2727 22 2: B -1.2727 26 3: C -1.2727 30
.SDcols
也能够是一个函数的返回值:
> DT[, lapply(.SD,sum), by=V2,
+ .SDcols = paste0("V",3:4)] V2 V3 V4 1: A -1.2727 22 2: B -1.2727 26 3: C -1.2727 30
结果与上一个是相同的。
> DT<-DT[, .(V4.Sum = sum(V4)),by=V1] > DT[V4.Sum > 35] #no chaining V1 V4.Sum 1: 1 36 2: 2 42
这个是不使用串联的方法,先以V1为分组,对V4求和,而后再把分组总和大于35的取出来。
使用串联的方法:
> DT[, .(V4.Sum = sum(V4)),by=V1][V4.Sum > 35 ] V1 V4.Sum 1: 1 36 2: 2 42
分组求和以后对V1进行排序:
> DT[, .(V4.Sum = sum(V4)),by=V1][order(-V1)] V1 V4.Sum 1: 2 42 2: 1 36
set()
家族set()
一般用来更新给定的行和列的值,要注意的是,他不能跟by结合使用。
> rows = list(3:4,5:6) > cols = 1:2 > for (i in seq_along(rows)) + { + set(DT, + i=rows[[i]], + j = cols[i], + value = NA) +} > DT V1 V2 V3 V4 1: 1 A -0.0559 1 2: 2 B -0.4450 2 3: NA C 0.0697 3 4: NA A -0.1547 4 5: 1 NA -0.0559 5 6: 2 NA -0.4450 6 7: 1 A 0.0697 7 8: 2 B -0.1547 8
以上程序把给定的一组行和列都设置为了NA
与set()
同理,setname()
能够修改给定的列名和行名,如下程序是
#把名字为"old"的列,设置为"new" > setnames(DT,"old","new") #把"V2","V3"列,设置为"V2.rating","V3.DataCamp" > setnames(DT,c("V2","V3"),c("V2.rating","V3.DataCamp"))
setcolorder()
能够用来修改列的顺序。
setcolorder(DT,c("V2","V1","V4","V3"))
这段代码会使得列的顺序变成:
[1] "V2" "V1" "V4" "V3"
栗子🌰:
首先介绍下data.table的语法,以下所示:
在data.table
包中,咱们可使用:=
引用来添加或更新列
内置的 order() 函数 * 咱们能够对一个字符型的列,使用减号“-”,来实现降序排列。
当咱们用list()
的时候,返回的是data.table,不用list()
时,返回的是向量。通常建议加上list()
,除非你就是想要获得向量格式的数据。
# select取子集方法之subset(x, subset, select)
注:subset特指对列的选择,select特指对行的选择, with = FALSE 来引用列名
* 既然列能够做为变量被引用,咱们能够直接引用咱们想选取的列。
* 既然咱们想选取全部的行,则可毋需指定参数 i。
* 返回了全部行的 arr_delay 列。
特殊的语法
.SD: data.table提供一个特殊的语法,形式是 .SD。它是 Subset of Data 的缩写。
它自身就是一个data.table,包含经过by 分组后的每一组。 回忆一下,一个data.table本质上是一个list,它们的列包含的元素个数都相同(其实就是行数)。
说明:
* .SD 包含除了分组依据的那一列之外的全部列。 * 返回值依旧保持了原数据的顺序。首先打印出来的是 ID=“b” 的数据,而后是 ID=“a” 的,最后是 ID=“c” 的。
为了对复数的列进行计算,咱们能够简单地使用函数 lapply()。
说明:
* .SD 分别包含了ID是 a、b、c的全部行,它们分别对应了各自的组。咱们应用函数 lapply() 对每列计算平均值。 * 每一组返回包含三个平均数的list,这些构成了最终返回的data.table。 * 既然函数 lapply() 返回 list,咱们就不须要在外面多加 .() 了。
-如何指定但愿计算平均值的列
.SDcols 使用参数 .SDcols。它接受列名或者列索引。好比,.SDcols = c("arr_delay", "dep_delay")能确保.SD之包含 arr_delay 和 dep_delay 这两列。 和 with = FALSE 同样,咱们也可使用 - 或者 ! 来移除列。好比,咱们指定 !(colA:colB) 或者 -(colA:colB)表示移除从 colA 到 colB 的全部列。
data.table的语法形式是:
DT[i, j, by]
指定参数i:
* 相似于data.frame,咱们能够subset行,除非不须要重复地使用 DT$,既然咱们能将列当作变量来引用。 * 咱们可使用order()排序。为了获得更快速的效果,order()函数内部使用了data.table的快速排序。 咱们能够经过参数i作更多的事,获得更快速的选取和连结。咱们能够在教程“Keys and fast binary search based subsets”和“Joins and rolling joins”中学到这些。
指定参数j:
* 以data.table的形式选取列:DT[, .(colA, colB)]。 * 以data.frame的形式选取列:DT[, c("colA", "colB"), with=FALSE]。 * 按列进行计算:DT[, .(sum(colA), mean(colB))]。 * 若是须要:DT[, .(sA =sum(colA), mB = mean(colB))]。 * 和i共同使用:DT[colA > value, sum(colB)]。
指定参数by:* 经过by,咱们能够指定列,或者列名,甚至表达式,进行分组。参数j能够很灵活地配置参数i和by实现强大的功能。
* by能够指定多个列,也能够指定表达式。 * 咱们能够用 keyby,对分组的结果自动排序。 * 咱们能够在参数j中指定 .SD 和 .SDcols,对复数的列进行操做。例如: 1.把函数fun 应用到全部 .SDcols指定的列上,同时对参数by指定的列进行分组:DT[, lapply(.SD, fun), by=., .SDcols=...]。 2.返回每组册前两行:DT[, head(.SD, 2), by=.]。 3.三个参数联合使用:DT[col > val, head(.SD, 1), by=.]
原文来自DataCamp课程的data.table官方速查表
原文连接:The data.table R package cheat sheet
http://youngspring1.github.io/post/2016/2016-03-13-datatable1/