R语言data.table速查手册

原文链接:http://blog.csdn.net/a358463121/article/details/51910062

介绍

R中的data.table包提供了一个data.frame的高级版本,让你的程序做数据整型的运算速度大大的增加。data.table已经在金融,基因工程学等领域大放光彩。他尤其适合那些需要处理大型数据集(比如 1GB 到100GB)需要在内存中处理数据的人。不过这个包的一些符号并不是很容易掌握,因为这些操作方式在R中比较少见。这也是这篇文章的目的,为了给大家提供一个速查的手册。


data.table的通用格式: DT[i, j, by],对于数据集DT,选取子集行i,通过by分组计算j

1.生成一个data.table对象

生成一个data.table对象,记为DT.

> 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2.通过i来筛选数据集的行

通过数字来筛选数据集的行

选取第三行到第五行

> 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
  • 1
  • 2
  • 3
  • 4
  • 5

基于使用快速自动索引条件,使用列名选择行i

在V2这一列,选择所有值为A的行

> 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

选择多个值:

选择在这一列中包含value1或value2的所有值

> DT[column %in% c("value1","value2")]
  • 1

选择V2这列中包含值A或C的所有行

> 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.通过j来操作列

通过j来选择一列

> DT[,V2]
[1]"A" "A" "A" "A" "B" "B" "B" "B" "C" "C" "C" "C"
  • 1
  • 2

注意到V2这一列是以向量的形式返回的

通过j来选择多列

> 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

V2与V3这两列以data.table的形式返回

.()为list()的一个别名。如果使用.(),返回的为一个data.table对象。如果不使用.(),结果为返回一个向量。

在j上调用函数

> DT[,sum(V1)]
[1] 18
  • 1
  • 2

以向量的形式返回V1列中所有元素的总和

在多列上进行计算

以data.table的形式,返回V1这列的所有元素之和与V3这列的标准差

> DT[,.(sum(V1),sd(V3))]
   V1        V2
1: 18 0.4546055
  • 1
  • 2
  • 3

指定计算列的列名

类似上例,但有一个新的列名

> DT[,.(Aggregate = sum(V1), Sd.V3 = sd(V3))]
   Aggregate     Sd.V3
1:        18 0.4546055
  • 1
  • 2
  • 3

若列的长度不一,则会循环对齐

选择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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

多个表达式可以包裹在花括号中

输出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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4.根据分组来操作j

根据分组来操作j

对V1中的每一类来计算V4列的和

> DT[,.(V4.Sum = sum(V4)),by=V1]
   V1 V4.Sum
1:  1     36
2:  2     42
  • 1
  • 2
  • 3
  • 4

通过使用.()控制多个列来操作j

与上例类似,但每一个分组包含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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在by中调用函数

以sign(V1-1)为分组,计算各个分组中V4列的和:

> DT[,.(V4.Sum = sum(V4)),by=sign(V1-1)]
   sign V4.Sum
1:    0     36
2:    1     42
  • 1
  • 2
  • 3
  • 4

通过指定i行子集的分组进行操作

在前5行数据集中,通过V1列的分组来计算V4列的总和:

> DT[1:5,.(V4.Sum = sum(V4)),by=V1]
   V1 V4.Sum
1:  1      8
2:  2     16
  • 1
  • 2
  • 3
  • 4

使用函数.N来得到每个类别的总观测数

在V1列中计算每个分组的观测数

> DT[,.N,by=V1]
   V1 N
1:  1 6
2:  2 6
  • 1
  • 2
  • 3
  • 4

5.使用:=引用来添加或更新一列

在一行中使用:=引用来添加或更新列.

注意: 额外的指定 (DT <- DT[…])是多余的 
使用:=来更新V1列:

> DT[, V1 := round(exp(V1),2)]
  • 1

这段代码没有显式的返回结果,而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])]
  • 1

同样没有显式的返回结果,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])][]
  • 1

与上例变化相同,但是由于在语句最后添加了[],这一结果会返回至屏幕

通过使用:=来移除一列

移除V1列

> DT[, V1 := NULL]
  • 1

无显式的返回结果,但V1列变为NULL

通过使用:=来移除多列

移除V1列与V2列

> DT[, c("V1","V2") := NULL]
  • 1

无显式的返回结果,但V1列与V2列变为NULL

将一个包含列名的变量用小括号包裹起来,变量所传递的内容将会被删除 
注意:列名为Cols.chosen的列将会被删除,这里不是删除”V1”,”V2”列

> Cols.chosen = c("V1","V2")
> DT[, Cols.chosen := NULL]
  • 1
  • 2

无显式的返回结果,列名为Cols.chosen的列将会被删除

删除指定变量Cols.chosen包含的V1列和V2列

> DT[, (Cols.chosen) := NULL]
  • 1

无显式的返回结果,列名为V1和V2的列变为NULL##索引与键值

使用setkey()函数设置键值

setkey()函数可以在数据集DT上设置键值。当我们设置好key后,data.table会将数据按照key来排序。 
在V2列上设置一个键值

> setkey(DT,V2)
  • 1

无显示返回结果

使用键值来选择行

使用键值可以更加有效地选择行 
由于已将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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

返回键值所在列(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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

mult参数

mult参数是用来控制i匹配到的哪一行的返回结果默认情况下会返回该分组的所有元素 
返回匹配到键值所在列(V2列)所有行中的第一行

> DT["A", mult ="first"]
   V1 V2 V3 V4
1: 1 A -1.1727 1
  • 1
  • 2
  • 3

返回匹配到键值所在列(V2列)所有行中的最后一行

> DT["A", mult = "last"]
   V1 V2 V3 V4
1: 2 A -0.3825 10
  • 1
  • 2
  • 3

nomatch参数

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

变量值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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

因为nomatch参数,值D没有匹配到故不返回。

by=.EACHI参数

by=.EACHI允许按每一个已知i的子集分组,在使用by=.EACHI时需要设置键值 
返回键值(V2列)中包含A或C的所有行中,V4列的总和。

> DT[c("A","C"),
sum(V4)]
[1] 52
  • 1
  • 2
  • 3

返回键值所在列(V2列)中包含A的行在V4列总和与包含C的行在V4列的总和。

> DT[c("A","C"),
sum(V4), by=.EACHI]
  V2 V1
1: A 22
2: C 30
  • 1
  • 2
  • 3
  • 4
  • 5

使用setkey()设置一个多列主键

任意列都能使用setkey()来设置主键,这种方式可以选择2个列作为一个主键。以下是一个等值连接V1列的每个组先根据V1排序,再根据V2排序。

> setkey(DT,V1,V2)
  • 1

无显式返回结果

选择键值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
  • 2
  • 3
  • 4

选择键值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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

6.data.table高级操作

.N

.N可以用来表示行的数量或者最后一行

在i处使用:

> DT[.N-1]
   V1 V2      V3 V4
1:  1  B -0.5765 11
  • 1
  • 2
  • 3

返回每一列的倒数第二行 
在j处使用:

> DT[,.N-1]
[1] 11
  • 1
  • 2

返回倒数第二行所在的行数。

.()

.()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
  • 1
  • 2
  • 3
  • 4
  • 5

在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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

以V1,V2为分组,对V3求均值

.SD参数

.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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

以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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

以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
  • 1
  • 2
  • 3
  • 4
  • 5

.SDcols

.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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

.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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

结果与上一个是相同的。

7.串联操作可以把表达式聚合在一起并避免多余的中间变量

把多个操作串联起来,这等价于SQL中的having

> DT<-DT[, .(V4.Sum = sum(V4)),by=V1]
> DT[V4.Sum > 35] #no chaining
V1 V4.Sum
1: 1 36
2: 2 42
  • 1
  • 2
  • 3
  • 4
  • 5

这个是不使用串联的方法,先以V1为分组,对V4求和,然后再把分组总和大于35的取出来。 
使用串联的方法:

> DT[, .(V4.Sum = sum(V4)),by=V1][V4.Sum > 35 ]
V1 V4.Sum
1: 1 36
2: 2 42
  • 1
  • 2
  • 3
  • 4

分组求和之后对V1进行排序:

> DT[, .(V4.Sum = sum(V4)),by=V1][order(-V1)]
V1 V4.Sum
1: 2 42
2: 1 36
  • 1
  • 2
  • 3
  • 4

8.使用set()家族

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

以上程序把给定的一组行和列都设置为了NA

setname()

set()同理,setname()可以修改给定的列名和行名,以下程序是

#把名字为"old"的列,设置为"new"
> setnames(DT,"old","new") 
#把"V2","V3"列,设置为"V2.rating","V3.DataCamp"
> setnames(DT,c("V2","V3"),c("V2.rating","V3.DataCamp")) 
  • 1
  • 2
  • 3
  • 4

setcolorder()

setcolorder()可以用来修改列的顺序。

setcolorder(DT,c("V2","V1","V4","V3")) 
  • 1

这段代码会使得列的顺序变成:

[1] "V2" "V1" "V4" "V3"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值