1. 程式人生 > >data.table基礎知識

data.table基礎知識

#載入航班資訊

#fread 快速檔案閱讀器

#使用data.table 親自建立

#如果列是字元型,則不能轉化成因子型(factor)

#data.table 不能設定和使用行名字。

> library(data.table)
> flights <- fread("flights14.csv")
> flights

> dim(flights)

 

> DT = data.table(ID = c("b","b","b","a","a","c"), a = 1:6, b = 7:12, c = 13:18)
> DT


   ID a  b  c
1:  b 1  7 13
2:  b 2  8 14
3:  b 3  9 15
4:  a 4 10 16
5:  a 5 11 17
6:  c 6 12 18
> class(DT$ID)
[1] "character"

> as.data.table()

> getOption("datatable.print.nrows")
[1] 100

 

#data.table 的基本形式,與sql語法作對比,便於理解

> DT[i, j, by]

 

##   R:      i                 j        by

## SQL:  where   select | update  group by

#Take DT, subset rows using i, then calculate j, grouped by by.

> ans <- flights[origin == "JFK" & month == 6L]
> dim(ans)

[1] 8422   17

 

選取行i

> flights[origin == "JFK" & month == 6L, ]#逗號可加可不加,data.frame中則必須要加

> ans <- flights[1:2]
> ans

> ans <- flights[order(origin, -dest)]# -dest 降序
> head(ans)

 

> odt = data.table(col = sample(1e7))
> t1 <- system.time(ans1 <- odt[base::order(col)]) ## uses order from base R
> t2 <- system.time(ans2 <- odt[order(col)]) ## uses data.table's forder#傳統R自帶包中的order與data.table中的order執行時間作對比
> (identical(ans1, ans2))  #比較兩變數是否相同,相同返回TRUE,否則FALSE

[1] TRUE

 

#選取列j

> ans <- flights[, arr_delay]   #變數格式
> head(ans)

[1]  13  13   9 -26   1   0
> ans <- flights[, list(arr_delay)] #返回data.table格式
> head(ans)

   arr_delay
1:        13
2:        13
3:         9
4:       -26
5:         1
6:         0
> ans <- flights[, .(arr_delay, dep_delay)] #等同於ans <- flights[, list(arr_delay, dep_delay)]
> head(ans)

   arr_delay dep_delay
1:        13        14
2:        13        -3
3:         9         2
4:       -26        -8
5:         1         2
6:         0         4

#重新命名

ans <- flights[, .(delay_arr = arr_delay, delay_dep = dep_delay)]

head(ans)

#關於j的計算

ans <- flights[, sum((arr_delay + dep_delay) < 0)]#[1] 141814 得到一個值 ,計算兩列數值相加小於0的個案個數

ans <- flights[, .((arr_delay + dep_delay) < 0)]

table(ans)

 

#計算6月份以“JFK”為原產地機場的所有航班的平均到達和離開延誤時間

ans <- flights[origin == "JFK" & month == 6L,.(m_arr = mean(arr_delay), m_dep = mean(dep_delay))] # 為什麼month == 6L

ans

#       m_arr    m_dep

# 1: 5.839349 9.807884

 

#data.frame 的操作方式

flights_test<-as.data.frame(flights)

ansx<-apply(flights_test[which(origin %in% "JFK" & month %in% 6),c(5,7)],2,mean)

ansx

#dep_delay arr_delay

#9.807884  5.839349

 

#在6月份的“JFK”機場2014年有多少次旅行?

ans <- flights[origin == "JFK" & month == 6L, length(dest)] #同下

ans

# [1] 8422

ans <- flights[origin == "JFK" & month == 6L, .N] #.N返回查詢的子集的行數

ans

# [1] 8422

nrow(flights[origin == "JFK" & month == 6L])#同上 低效

 

按名稱引用列

#設定with = FALSE禁止引用列的功能,就像它們是變數一樣,從而恢復“ data.frame模式”

ans <- flights[, c("arr_delay", "dep_delay"),with = FALSE]

head(ans)

 

ans <- flights[, !c("arr_delay", "dep_delay"), with = FALSE]#取消列的選擇

ans <- flights[, -c("arr_delay", "dep_delay"), with = FALSE]#取消列的選擇

#通過指定開始和結束列名year:day來選擇

ans<-flights[,year: day,with = FALSE]

ans<-flights[,!(year: day),with = FALSE]

ans<-flights[,-(year: day),with = FALSE]

 

  使用分組 

ans <- flights[, .(.N), by = .(origin)]

ans

#origin     N

#1:    JFK 81483

#2:    LGA 84433

#3:    EWR 87400

#同上    ans<-flights[,.(.N),by="origin"]

 

#如果只有一列或表示式來引用j和by,我們可以刪除.()符號。

ans <- flights[, list(.N), by = list(origin)]

ans <- flights[, .N, by = origin]

#如何計算每個起運機場的航空公司程式碼為“AA”的旅行次數?

ans <- flights[carrier == "AA", .N, by = origin]

ans

#怎樣才能得到每origin, dest對貨運程式碼為“AA”的旅行總次數?

ans <- flights[carrier == "AA", .N, by = .(origin,dest)]

#orig,dest運營商程式碼“AA”每月如何得到每對貨物的平均到達和離開延遲?

ans <- flights[carrier == "AA",

               .(mean(arr_delay), mean(dep_delay)),

               by = .(origin, dest, month)]  #月份排序

 

ans <- flights[carrier == "AA",

               .(mean(arr_delay), mean(dep_delay)),

               keyby = .(origin, dest, month)]  #月份排序

ans

 

#對origin升序,dest降序,對結果進行重排列

ans <- flights[carrier == "AA", .N, by = .(origin, dest)][order(origin, -dest)]

 

連結[chain]

 

如:

 ans <- flights[carrier == "AA", .N, by = .(origin, dest)][order(origin, -dest)]

 head(ans, 10)

 

可以一直鏈接下去,形式如:DT[ ... ][ ... ][ ... ]

或者進行垂直鏈接:

DT[ ...

][ ...

][ ...

]

 

by中的表示式

 

by也可以接受表示式或列,如想知道哪一個航班起步較晚,但是提前達到,可以寫成:

ans <- flights[, .N, .(dep_delay>0, arr_delay>0)]

ans

   dep_delay arr_delay      N
1:      TRUE      TRUE  72836
2:     FALSE      TRUE  34583
3:     FALSE     FALSE 119304
4:      TRUE     FALSE  26593

 

最後一行對應於dep_delay > 0 = TRUE和arr_delay > 0 = FALSE。我們可以看到,26593班航班起步晚,但提早(或按時)到達。

 

 

j 中含有多列--.SD

 

> DT
   ID a  b  c
1:  b 1  7 13
2:  b 2  8 14
3:  b 3  9 15
4:  a 4 10 16
5:  a 5 11 17
6:  c 6 12 18

 

> DT[,print(.SD),by=ID]
   a b  c
1: 1 7 13
2: 2 8 14
3: 3 9 15
   a  b  c
1: 4 10 16
2: 5 11 17
   a  b  c
1: 6 12 18
Empty data.table (0 rows) of 1 col: ID

 

.SD包含出分組以外的所有的列。可以用apply進行計算。

> DT[,lapply(.SD,mean),by=ID]
   ID   a    b    c
1:  b 2.0  8.0 14.0
2:  a 4.5 10.5 16.5
3:  c 6.0 12.0 18.0

因為apply()返回的就是列表格式,因此不需要再使用 “.()”.

 

指定想要計算的列的均值mean

 

使用引數 .SDcols()

 

flights[carrier == "AA",                       ## Only on trips with carrier "AA"

        lapply(.SD, mean),                     ## compute the mean

        by = .(origin, dest, month),           ## for every 'origin,dest,month'

        .SDcols = c("arr_delay", "dep_delay")] ## for just those specified in .SDcols

 

     origin dest month  arr_delay  dep_delay
  1:    JFK  LAX     1   6.590361 14.2289157
  2:    LGA  PBI     1  -7.758621  0.3103448
  3:    EWR  LAX     1   1.366667  7.5000000
  4:    JFK  MIA     1  15.720670 18.7430168
  5:    JFK  SEA     1  14.357143 30.7500000
 ---                                       
196:    LGA  MIA    10  -6.251799 -1.4208633
197:    JFK  MIA    10  -1.880184  6.6774194
198:    EWR  PHX    10  -3.032258 -4.2903226
199:    JFK  MCO    10 -10.048387 -1.6129032
200:    JFK  DCA    10  16.483871 15.5161290

 

.SD 每個組的子集

 

> ans <- flights[, head(.SD, 2), by = month]
> ans

提取每個月的前兩個的子集

1

1

2

2

3

3

 

保持j的靈活性

 

DT[,.(val=c(a,b)),by=ID]
    ID val
 1:  b   1
 2:  b   2
 3:  b   3
 4:  b   7
 5:  b   8
 6:  b   9
 7:  a   4
 8:  a   5
 9:  a  10
10:  a  11
11:  c   6
12:  c  12

 

DT[,.(val=list(c(a,b))),by=ID]
   ID         val
1:  b 1,2,3,7,8,9
2:  a  4, 5,10,11
3:  c        6,12

 

總結

 

data.table 的語法形式是:data.table[i,j,by]

 

使用i:

1.可以採用與資料框類似的提取子集的方式

2.使用order對data.table進行排序

 

使用j:

1.選擇列的data.table 方式:DT[,.(colA,colB)]

2.選擇data.frame的方式:DT[,c("colA","colB"),with = FALSE]

3.在列上計算:DT[,.(sum(colA),mean(colB))]

4.如有必要提供列名:DT[,.(sA=sum(colA),mB=mean(colB))]

5.結合i:DT[colA > value,sum(colB)]

 

 

使用by:

1. `DT[, lapply(.SD, fun), by = ..., .SDcols = ...]

--對SDcols中選擇的所有列進行函式fun計算,通過by分組進行分組計算

2. `DT[, head(.SD, 2), by = ...] --返回每組的前兩行資料

3. `DT[col > val, head(.SD, 1), by = ...]`

---先選擇滿足col > val的行,然後通過by進行分組,最後提取每組中的第一行資料。