R中的data.table 快速上手入門


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM