为什么要学习data.table

一直使用这个包的fread函数, 读取数据确实很快, fwrite写入也非常快. 看到大牛在用data.table的key功能, 感觉这个包还有很多需要学习的地方, 利用网上的信息, 加上自己的操作, 记录学习的过程.

语法特点

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

1, 生成一个data.table格式的对象, 下面用DT为data.table格式的简写

library(data.table)
set.seed(123)
DT <- data.table(V1=c(1,2),V2=c("A","B","C"),V3=round(rnorm(4),4), V4=1:12)
DT
V1 V2 V3 V4
1 A -0.5605 1
2 B -0.2302 2
1 C 1.5587 3
2 A 0.0705 4
1 B -0.5605 5
2 C -0.2302 6
1 A 1.5587 7
2 B 0.0705 8
1 C -0.5605 9
2 A -0.2302 10
1 B 1.5587 11
2 C 0.0705 12

2, 通过i来进行行的筛选

如果只有一个值, 不用加逗号, 默认的是选取行.

DT[2]
V1 V2 V3 V4
2 B -0.2302 2
DT[2,]
V1 V2 V3 V4
2 B -0.2302 2

选择3:5行的数据

DT[3:5]
V1 V2 V3 V4
1 C 1.5587 3
2 A 0.0705 4
1 B -0.5605 5
DT[3:5,]
V1 V2 V3 V4
1 C 1.5587 3
2 A 0.0705 4
1 B -0.5605 5

根据V2列的值, 选择V2==A的数据

DT[V2=="A"]
V1 V2 V3 V4
1 A -0.5605 1
2 A 0.0705 4
1 A 1.5587 7
2 A -0.2302 10
DT[V2=="A",]
V1 V2 V3 V4
1 A -0.5605 1
2 A 0.0705 4
1 A 1.5587 7
2 A -0.2302 10

根据V2列的值, 选择V2==A或者C的数据

DT[V2=="A"|V2=="C"]
V1 V2 V3 V4
1 A -0.5605 1
1 C 1.5587 3
2 A 0.0705 4
2 C -0.2302 6
1 A 1.5587 7
1 C -0.5605 9
2 A -0.2302 10
2 C 0.0705 12
DT[V2 %in% c("A","C")]
V1 V2 V3 V4
1 A -0.5605 1
1 C 1.5587 3
2 A 0.0705 4
2 C -0.2302 6
1 A 1.5587 7
1 C -0.5605 9
2 A -0.2302 10
2 C 0.0705 12

3, 通过j来进行列的筛选

选择第二列

DT[,2]
V2
A
B
C
A
B
C
A
B
C
A
B
C

选择第二列, 第三列

DT[,2:3]
V2 V3
A -0.5605
B -0.2302
C 1.5587
A 0.0705
B -0.5605
C -0.2302
A 1.5587
B 0.0705
C -0.5605
A -0.2302
B 1.5587
C 0.0705
DT[,c(2,3)]
V2 V3
A -0.5605
B -0.2302
C 1.5587
A 0.0705
B -0.5605
C -0.2302
A 1.5587
B 0.0705
C -0.5605
A -0.2302
B 1.5587
C 0.0705

可以使用列名进行选择, 但是直接选择是向量

DT[,V1]
  1. 1
  2. 2
  3. 1
  4. 2
  5. 1
  6. 2
  7. 1
  8. 2
  9. 1
  10. 2
  11. 1
  12. 2

如果是多个名称, 返回的也是向量, 如果想要DT格式, 需要用list或者.()的形式

DT[,c(V1,V2)]
  1. '1'
  2. '2'
  3. '1'
  4. '2'
  5. '1'
  6. '2'
  7. '1'
  8. '2'
  9. '1'
  10. '2'
  11. '1'
  12. '2'
  13. 'A'
  14. 'B'
  15. 'C'
  16. 'A'
  17. 'B'
  18. 'C'
  19. 'A'
  20. 'B'
  21. 'C'
  22. 'A'
  23. 'B'
  24. 'C'
DT[,list(V1,V2)]
V1 V2
1 A
2 B
1 C
2 A
1 B
2 C
1 A
2 B
1 C
2 A
1 B
2 C
DT[,.(V1,V2)]
V1 V2
1 A
2 B
1 C
2 A
1 B
2 C
1 A
2 B
1 C
2 A
1 B
2 C

这里注意, .()为list()的一个别名, 在选择列时, 如果使用.()返回的是DT对象, 如果不使用.()则返回的是一个向量

3, 在j上调用函数

DT[,sum(V1)]

18

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

DT[,.(sum(V1),sd(V3))]
V1 V2
18 0.8462588

可以赋予名称

DT[,.(he =sum(V1),xx=sd(V3))]
he xx
18 0.8462588

4, 根据分组来操作j

DT[,.(V4.Sum = sum(V4)),by=V1]
V1 V4.Sum
1 36
2 42
DT
V1 V2 V3 V4
1 A -0.5605 1
2 B -0.2302 2
1 C 1.5587 3
2 A 0.0705 4
1 B -0.5605 5
2 C -0.2302 6
1 A 1.5587 7
2 B 0.0705 8
1 C -0.5605 9
2 A -0.2302 10
1 B 1.5587 11
2 C 0.0705 12

这个类似:

sum(DT[V1==1,4]);
sum(DT[V1==2,4])

36

42

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

DT[,.N,by=V1]
V1 N
1 6
2 6

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

如果想要在原来列的基础上, 生成新的列, 可以使用:=

相当于原位编辑, 保存为对象DT,DT V 5 = D T V5=DT V5=DTV4^2

DT[,V5:=V4^2]

DT
V1 V2 V3 V4 V5
1 A -0.5605 1 1
2 B -0.2302 2 4
1 C 1.5587 3 9
2 A 0.0705 4 16
1 B -0.5605 5 25
2 C -0.2302 6 36
1 A 1.5587 7 49
2 B 0.0705 8 64
1 C -0.5605 9 81
2 A -0.2302 10 100
1 B 1.5587 11 121
2 C 0.0705 12 144

删除第五列

DT[,V5:=NULL]
DT
V1 V2 V3 V4
1 A -0.5605 1
2 B -0.2302 2
1 C 1.5587 3
2 A 0.0705 4
1 B -0.5605 5
2 C -0.2302 6
1 A 1.5587 7
2 B 0.0705 8
1 C -0.5605 9
2 A -0.2302 10
1 B 1.5587 11
2 C 0.0705 12
DT[,V5:=V4^2]

DT
V1 V2 V3 V4 V5
1 A -0.5605 1 1
2 B -0.2302 2 4
1 C 1.5587 3 9
2 A 0.0705 4 16
1 B -0.5605 5 25
2 C -0.2302 6 36
1 A 1.5587 7 49
2 B 0.0705 8 64
1 C -0.5605 9 81
2 A -0.2302 10 100
1 B 1.5587 11 121
2 C 0.0705 12 144
DT[,5:=NULL]
DT
V1 V2 V3 V4
1 A -0.5605 1
2 B -0.2302 2
1 C 1.5587 3
2 A 0.0705 4
1 B -0.5605 5
2 C -0.2302 6
1 A 1.5587 7
2 B 0.0705 8
1 C -0.5605 9
2 A -0.2302 10
1 B 1.5587 11
2 C 0.0705 12

这里, 删除可以是第五列的名称(V5), 也可以是第五列(5)

6, 使用.N指定最后一行

DT[.N]
V1 V2 V3 V4
2 C 0.0705 12

选择倒数5行

DT[.N-5:.N]
V1 V2 V3 V4
1 A 1.5587 7
2 C -0.2302 6
1 B -0.5605 5
2 A 0.0705 4
1 C 1.5587 3
2 B -0.2302 2
1 A -0.5605 1

总结

  • 1, data.table不仅仅fread和fwrite强大, 进行行和列筛选时, 也很强大

  • 2, 默认一个参数时, 是指定的行, 行默认是返回的DT, 如果是列名时, 默认返回的向量,可以用list或者.()进行定义

  • 3, 使用:=进行原位编辑, 可以更新列, 生成新列, 删除列

  • 4, .N这是最后一列, 是一个简化的符号, 比较方便