为什么要学习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
- 2
- 1
- 2
- 1
- 2
- 1
- 2
- 1
- 2
- 1
- 2
如果是多个名称, 返回的也是向量, 如果想要DT格式, 需要用list或者.()的形式
DT[,c(V1,V2)]
- '1'
- '2'
- '1'
- '2'
- '1'
- '2'
- '1'
- '2'
- '1'
- '2'
- '1'
- '2'
- 'A'
- 'B'
- 'C'
- 'A'
- 'B'
- 'C'
- 'A'
- 'B'
- 'C'
- 'A'
- 'B'
- '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这是最后一列, 是一个简化的符号, 比较方便