原文鏈接: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"