data.table包提供了一個非常簡潔的通用格式:DT[i,j,by]。
可以理解為:對於數據集DT,選取子集行i,通過by分組計算j。
對比與dplyr等包,data.table的運行速度更快。
創建方式和data.frame 一樣 創建一個data.frame: DF = data.frame(x=c("b","b","b","a","a"),v=rnorm(5)) 創建一個data.table: DT = data.table(x=c("b","b","b","a","a"),v=rnorm(5)) data.frame轉換為data.table類型: DT = data.table(DF)
查看內存中所有的data.table
tables()
構建一個數據集用於測試
library(data.table) CARS = data.table(cars) X=data.table(speed=c(4,7,8),type=c("small","middle","large")) dt <- CARS[X,on='speed'] tables() dt # speed dist type # 1: 4 2 small # 2: 4 10 small # 3: 7 4 middle # 4: 7 22 middle # 5: 8 16 large
Keys
Keys在data.table中是一個重要的概念,在一個data.table中只能設置一個key,但是這一個key可以包含多個列。當我們設置好key后,data.table會將數據按照key來排序。
# 選取第二行 dt[2,] # 選取speed=4 的行 dt[speed==4] # 更快,更簡單的表達 #篩選行 setkey(dt,type) dt["small"] dt[c("small","large")] dt[.("small","large")] dt["small",mult='first'] dt["small",mult='last'] dt[speed %between% c(7,8)] dt[speed %in% c(7,8)] all.equal(ans1,ans2) #把列當作行 篩選其他列 dt["small",speed] dt["small","speed"] dt["small",2] dt["small",2,on="type"]# on 相當於使用了setkey # 篩選列 # 選取第一列 dt[,1] # 選取第一到第二列 dt[,1:2] # 選取列也可以直接輸入列名 dt[,.(speed,dist)] # 排序 speed升序,dist降序排列 setorder(dt,speed,-dist) 刪選子集 選取子集仍然采用subset函數,調用公式為: # subset是行滿足條件 # select是列滿足條件 > subset(x, subset, select) subset(dt,speed==8,select =c('speed','dist'))
重排序數據框的列
可以通過數值位置重排序:
1
2
|
# 通過列的數值位置重排序
dat = dat[
c
(1,3,2)]
|
也可以通過列的名稱重排序:
1
2
|
# 通過列的名稱重排序
dat = dat[
c
(
"col1"
,
"col3"
,
"col2"
)]
|
# 接下下我們創建一個1000萬行的數據,用來演示data.table的性能 grpsize = ceiling(1e7/26^2) # 10 million rows, 676 groups tt=system.time( DF <- data.frame( x=rep(LETTERS,each=26*grpsize), y=rep(letters,each=grpsize), v=runif(grpsize*26^2), stringsAsFactors=FALSE) ) dim(DF)
我們試試將DF中x為“R”的行與y為”h”的行提取出來
system.time(ans1 <- DF[DF$x=="R" & DF$y=="h",]) # 用戶 系統 流逝 # 0.06 0.08 0.14 DT = as.data.table(DF) system.time(setkey(DT,x,y)) # 用戶 系統 流逝 # 0.05 0.01 0.07 system.time(ans2 <- DT[list("R","h")]) # 用戶 系統 流逝 0 0 0 x與y這兩列返回一個data.table data.table也允許用 .() 來包圍列名,它是 list() 的別名,它們的效果是同樣的。如果不使用.()或者list,結果為返回一個向量
可以看到,當我們設置好key后,提取行的操作基本不需要等待時間,比我們平時用的操作快了100倍。要注意的是,如果使用”==”操作符,那么它會掃描整個數組,雖然data.table用這種方法也可以提取,但很慢,要盡量避免。
system.time(ans1 <- DT[x=="R" & y=="h"]) # works but is using data.table badly # 用戶 系統 流逝 # 0.06 0.04 0.11
(不建議這樣使用)
下面我們要看data.table的第二個參數
DT[,sum(v)] ## [1] 4999770 head(DT[,sum(v),by=x])
以上代碼以x為分組,依次調用sum函數,統計了每個分組x的總和。
# 單一分組 dt[,.(total=sum(dist),avg=mean(dist)),by=type] # type total avg # 1: small 12 6 # 2: middle 26 13 # 3: large 16 16 # 多分組 dt[,.(total=sum(dist),avg=mean(dist)),by=list(type,speed)] # data.table有一個特殊的變量.N可以直接計算分組的觀測值個數。 dt[,.N,by=type]
顯然這一功能在plyr包和dplyr包也有相對應的函數實現,接下來我們比較一下這3個包的速度。
#plyr包 system.time( ddply(DF,.(x),function(x)sum(x$v)) ) ## user system elapsed ## 1.71 0.22 1.94 #dplyr包 system.time({ DF%>% group_by(x)%>% summarise(sum(v)) }) ## user system elapsed ## 0.60 0.12 0.72 #data.table包 DT = as.data.table(DF) system.time({ DT[,sum(v),by=x] }) ## user system elapsed ## 0.12 0.02 0.14
增加刪除列
# 單變量添加
DT[i, LHS:=RHS, by=...]
# LHS為新建的變量,RHS為該變量的計算方式
# 雙變量添加
DT[i, c("LHS1","LHS2") := list(RHS1, RHS2), by=...]
# #多變量添加,注意`:=`
DT[i, `:=`(LHS1=RHS1,LHS2=RHS2,...), by=...]
# 單變量 dt[,total:=speed+dist] # speed dist type total # 1: 4 10 small 14 # 2: 4 2 small 6 # 3: 7 22 middle 29 # 4: 7 4 middle 11 # 5: 8 16 large 24 # 刪除變量(變量:=NULL即可) dt[,total:=NULL]
#當我們把data.frame數據框轉化成data.table時,默認拋棄行名,不過我們也可以用一個參數保留行名成為新的一列
df1 <- data.frame(weight,height,row.names = name1) dt1 <- as.data.table(df1) dt2 <- as.data.table(df1,keep.rownames=T) # 將原來數據框中的行名當成一列,列名為rn dt1;dt2 as.data.table(df1,keep.rownames = "rownames") # 自己指定新增列的列名
# 數據合並仍然采用merge函數,只是合並對象必須是data.table類型,這樣才能發揮出data.table的威力!
> merge(x, y, by = NULL, by.x = NULL, by.y = NULL,all = FALSE, all.x = all, all.y = all, sort = TRUE, suffixes = c(".x", ".y"), allow.cartesian=getOption("datatable.allow.cartesian"), ...)
dt1 <- data.table(A = letters[1:10], X = 1:10, key = "A") dt2 <- data.table(A = letters[5:14], Y = 1:10, key = "A")
join 連接操作
使用DT[X],該操作會將X中key(沒指定key則默認第一列)與DT的key作連接,同理,X[DT]會將DT與X作連接
DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9)
DT ## x y v ## 1: a 1 1 ## 2: a 3 2 ## 3: a 6 3 ## 4: b 1 4 ## 5: b 3 5 ## 6: b 6 6 ## 7: c 1 7 ## 8: c 3 8
## 9: c 6 9
X = data.table(c("b","c"),foo=c(4,2)) X ## V1 foo ## 1: b 4 ## 2: c 2
setkey(DT,x) DT[X] ## x y v foo ## 1: b 1 4 4 ## 2: b 3 5 4 ## 3: b 6 6 4 ## 4: c 1 7 2 ## 5: c 3 8 2 ## 6: c 6 9 2 setkey(X,V1) X[DT] ## V1 foo y v ## 1: a NA 1 1 ## 2: a NA 3 2 ## 3: a NA 6 3 ## 4: b 4 1 4 ## 5: b 4 3 5 ## 6: b 4 6 6 ## 7: c 2 1 7 ## 8: c 2 3 8 ## 9: c 2 6 9
我們也可以使用on操作來連接兩個相同的列:
DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9) X = data.table(x=c("b","c"),foo=c(4,2)) DT[X, on="x"] # join on columns 'x' ## x y v foo ## 1: b 1 4 4 ## 2: b 3 5 4 ## 3: b 6 6 4 ## 4: c 1 7 2 ## 5: c 3 8 2 ## 6: c 6 9 2
本文出自:http://blog.csdn.net/a358463121,感謝分享~
參考文獻:https://cran.r-project.org/web/packages/data.table/data.table.pdf
Data.Table若干高級技巧
http://blog.csdn.net/iqqiqqiqqiqq/article/details/51812957
關於dplyr 和data.table的比較 可參考:
http://www.xueqing.tv/cms/article/213