#加载航班信息
#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进行分组,最后提取每组中的第一行数据。