library(data.table)
library(dplyr)
library(plotly)
Завантажимо дані по польотах flights14 використовуючи функцію fread().
address <- "https://raw.githubusercontent.com/wiki/arunsrinivasan/flights/NYCflights14/flights14.csv"
flights <- fread(address, showProgress = T)
Подивимось на дані:
glimpse(flights)
## Observations: 253,316
## Variables: 17
## $ year (int) 2014, 2014, 2014, 2014, 2014, 2014, 2014, 2014, 2014...
## $ month (int) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
## $ day (int) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
## $ dep_time (int) 914, 1157, 1902, 722, 1347, 1824, 2133, 1542, 1509, ...
## $ dep_delay (int) 14, -3, 2, -8, 2, 4, -2, -3, -1, -2, -5, 7, 3, 142, ...
## $ arr_time (int) 1238, 1523, 2224, 1014, 1706, 2145, 37, 1906, 1828, ...
## $ arr_delay (int) 13, 13, 9, -26, 1, 0, -18, -14, -17, -14, -17, -5, 1...
## $ cancelled (int) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ carrier (chr) "AA", "AA", "AA", "AA", "AA", "AA", "AA", "AA", "AA"...
## $ tailnum (chr) "N338AA", "N335AA", "N327AA", "N3EHAA", "N319AA", "N...
## $ flight (int) 1, 3, 21, 29, 117, 119, 185, 133, 145, 235, 172, 177...
## $ origin (chr) "JFK", "JFK", "JFK", "LGA", "JFK", "EWR", "JFK", "JF...
## $ dest (chr) "LAX", "LAX", "LAX", "PBI", "LAX", "LAX", "LAX", "LA...
## $ air_time (int) 359, 363, 351, 157, 350, 339, 338, 356, 161, 349, 16...
## $ distance (int) 2475, 2475, 2475, 1035, 2475, 2454, 2475, 2475, 1089...
## $ hour (int) 9, 11, 19, 7, 13, 18, 21, 15, 15, 18, 16, 17, 12, 19...
## $ min (int) 14, 57, 2, 22, 47, 24, 33, 42, 9, 48, 55, 52, 53, 7,...
Структура таблиці data.table: DT [ i , j , by ] . i - робота із рядками; j - що обчислити; by - як згрупувати.
i.Виберемо всі рейси із початковою точкою (аеропортом) “JFK” за червень:
ans <- flights[origin == "JFK" & month == 6]
head(ans, 5)
## year month day dep_time dep_delay arr_time arr_delay cancelled carrier
## 1: 2014 6 1 851 -9 1205 -5 0 AA
## 2: 2014 6 1 1220 -10 1522 -13 0 AA
## 3: 2014 6 1 718 18 1014 -1 0 AA
## 4: 2014 6 1 1024 -6 1314 -16 0 AA
## 5: 2014 6 1 1841 -4 2125 -45 0 AA
## tailnum flight origin dest air_time distance hour min
## 1: N787AA 1 JFK LAX 324 2475 8 51
## 2: N795AA 3 JFK LAX 329 2475 12 20
## 3: N784AA 9 JFK LAX 326 2475 7 18
## 4: N791AA 19 JFK LAX 320 2475 10 24
## 5: N790AA 21 JFK LAX 326 2475 18 41
У порівнянні із data.frame не потрібно використовувати символ $ (DT$colA), тобто до стовбців таблиці звертаємось як до змінних.
Вибрати перші два рядки таблиці:
ans <- flights[1:2]
ans
## year month day dep_time dep_delay arr_time arr_delay cancelled carrier
## 1: 2014 1 1 914 14 1238 13 0 AA
## 2: 2014 1 1 1157 -3 1523 13 0 AA
## tailnum flight origin dest air_time distance hour min
## 1: N338AA 1 JFK LAX 359 2475 9 14
## 2: N335AA 3 JFK LAX 363 2475 11 57
Відсортувати flights по колонці origin в порядку збільшення, а потім dest в порядку зменшення:
ans <- flights[order(origin, -dest)]
head(ans)
## year month day dep_time dep_delay arr_time arr_delay cancelled carrier
## 1: 2014 1 5 836 6 1151 49 0 EV
## 2: 2014 1 6 833 7 1111 13 0 EV
## 3: 2014 1 7 811 -6 1035 -13 0 EV
## 4: 2014 1 8 810 -7 1036 -12 0 EV
## 5: 2014 1 9 833 16 1055 7 0 EV
## 6: 2014 1 13 923 66 1154 66 0 EV
## tailnum flight origin dest air_time distance hour min
## 1: N12175 4419 EWR XNA 195 1131 8 36
## 2: N24128 4419 EWR XNA 190 1131 8 33
## 3: N12142 4419 EWR XNA 179 1131 8 11
## 4: N11193 4419 EWR XNA 184 1131 8 10
## 5: N14198 4419 EWR XNA 181 1131 8 33
## 6: N12157 4419 EWR XNA 188 1131 9 23
Відбувається автоматичне переформатування функції base::order() в forder, яка працює в рази швидше:
t.1 <- system.time(flights[base::order(origin)])
t.2 <- system.time(flights[order(origin)])
t.1; t.2
## user system elapsed
## 1.376 0.010 1.386
## user system elapsed
## 0.030 0.009 0.039
j.Вибрати стовбець arr_delay і повернути його як vector:
ans <- flights[, arr_delay]
head(ans)
## [1] 13 13 9 -26 1 0
Вибрати стовбець arr_delay і повернути як data.table- потрібно обернути змінну в list() або .(). (.() - це псевдонім list()):
ans <- flights[, .(arr_delay)]
head(ans)
## arr_delay
## 1: 13
## 2: 13
## 3: 9
## 4: -26
## 5: 1
## 6: 0
data.table i data.frame - це списки із стовбцями рівної довжини і вказаними класами (типами даних)Вибрати стовбці arr_delay i dep_delay:
ans <- flights[, .(arr_delay, dep_delay)]
head(ans, 5)
## arr_delay dep_delay
## 1: 13 14
## 2: 13 -3
## 3: 9 2
## 4: -26 -8
## 5: 1 2
Вибрати стобці arr_delay i dep_delay, переіменувати їх в delay_arr i delay_dep:
ans <- flights[, .(delay_arr = arr_delay, delay_dep = dep_delay)]
head(ans)
## delay_arr delay_dep
## 1: 13 14
## 2: 13 -3
## 3: 9 2
## 4: -26 -8
## 5: 1 2
## 6: 0 4
Скільки рейсів мали загальну затримку delay < 0 ?:
ans <- flights[, sum((arr_delay + dep_delay) < 0)]
ans
## [1] 141814
Розрахувати середню затримку прильоту і відльоту для всіх рейсів з початковою точкою JFK за червень:
ans <- flights[i = origin == "JFK" & month == 6,
j = .(m.arr = mean(arr_delay), m.dep = mean(dep_delay))]
ans
## m.arr m.dep
## 1: 5.839349 9.807884
Скільки рейсів було зроблено в 2014 році із аеропорту JFK за червень:
ans <- flights[i = year == 2014 & origin == "JFK" & month == 6,
j = length(dest)]
ans
## [1] 8422
Можна використати .N для визначення кількості даних в піднаборі (особливо корисно при використанні із by):
ans.1 <- flights[i = year == 2014 & origin == "JFK" & month == 6,
j = .N] # vector
ans.2 <- flights[i = year == 2014 & origin == "JFK" & month == 6,
j = .(count = .N)] # data.table
ans.1; ans.2
## [1] 8422
## count
## 1: 8422
Вибрати стовбці arr_delay і dep_delay як в data.frame (треба поставити аргумент with = FALSE - заборона посилання на стовбці як на змінні):
ans <- flights[, c("arr_delay", "dep_delay"), with = FALSE]
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[, year:day, with = FALSE]
head(ans)
## year month day
## 1: 2014 1 1
## 2: 2014 1 1
## 3: 2014 1 1
## 4: 2014 1 1
## 5: 2014 1 1
## 6: 2014 1 1
by.Визначити кількість рейсів по кожному аеропорту:
ans <- flights[, .(count = .N), by = origin]
ans
## origin count
## 1: JFK 81483
## 2: LGA 84433
## 3: EWR 87400
Розрахувати кількість рейсів із кожного аеропорту перевізника АА:
ans <- flights[i = carrier == "AA",
j = .(count = .N),
by = origin]
ans
## origin count
## 1: JFK 11923
## 2: LGA 11730
## 3: EWR 2649
К-сть рейсів для origin i dest перевізника АА:
ans <- flights[carrier == "AA",
.(count = .N),
by = .(origin, dest)]
head(ans)
## origin dest count
## 1: JFK LAX 3387
## 2: LGA PBI 245
## 3: EWR LAX 62
## 4: JFK MIA 1876
## 5: JFK SEA 298
## 6: EWR MIA 848
Середня затримка прильоту і відльоту для кожної пари origin i dest в кожному місяці перевізника АА:
ans <- flights[carrier == "AA",
.(m.arr = mean(arr_delay), m.dep = mean(dep_delay)),
.(origin, dest, month)]
ans
## origin dest month m.arr m.dep
## 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
Впорядкувати по змінним, які групуються - замість by вказати keyby:
ans <- flights[carrier == "AA",
.(m.arr = mean(arr_delay), m.dep = mean(dep_delay)),
keyby = .(origin, dest, month)]
ans
## origin dest month m.arr m.dep
## 1: EWR DFW 1 6.427673 10.0125786
## 2: EWR DFW 2 10.536765 11.3455882
## 3: EWR DFW 3 12.865031 8.0797546
## 4: EWR DFW 4 17.792683 12.9207317
## 5: EWR DFW 5 18.487805 18.6829268
## ---
## 196: LGA PBI 1 -7.758621 0.3103448
## 197: LGA PBI 2 -7.865385 2.4038462
## 198: LGA PBI 3 -5.754098 3.0327869
## 199: LGA PBI 4 -13.966667 -4.7333333
## 200: LGA PBI 5 -10.357143 -6.8571429
Визначити к-сть рейсів для кожної пари origin i dest перевізника АА і впорядкувати ans по origin в порядку зростання і dest в порядку зменшення:
ans <- flights[carrier == "AA", .N, by = .(origin, dest)]
ans <- ans[order(origin, -dest)]
head(ans)
## origin dest N
## 1: EWR PHX 121
## 2: EWR MIA 848
## 3: EWR LAX 62
## 4: EWR DFW 1618
## 5: JFK STT 229
## 6: JFK SJU 690
Але краще використати Ланцюжок (chaining) - можна не зберігати таблицю, а зразу сортувати:
ans <- flights[carrier == "AA", .N, by = .(origin, dest)][order(origin, -dest)]
head(ans)
## origin dest N
## 1: EWR PHX 121
## 2: EWR MIA 848
## 3: EWR LAX 62
## 4: EWR DFW 1618
## 5: JFK STT 229
## 6: JFK SJU 690
j - .SD (Subset of Data).DT <- data.table(ID = c("a", "a", "a", "b", "b", "c"), a = 1:6, b = 7:12, c = 13:18)
DT
## ID a b c
## 1: a 1 7 13
## 2: a 2 8 14
## 3: a 3 9 15
## 4: b 4 10 16
## 5: b 5 11 17
## 6: c 6 12 18
.SD зберігає в собі всі колонки окрім колонки в by, створюються дані, які відповідають відповідно даним в групуючій колонці.
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
Щоб розрахувати середнє для кожного значення із ID, для всіх колонок використаємо lapply(оскільки data.table - це список, елементи якого це колонки). Оскільки lapply повертає список, то не треба додатково заключати її в .():
ans <- DT[, lapply(.SD, mean), by = ID]
ans
## ID a b c
## 1: a 2.0 8.0 14.0
## 2: b 4.5 10.5 16.5
## 3: c 6.0 12.0 18.0
Для того, щоб вибрати вибрати необхідні нам стовбці потрібно використовувати аргумент .SDcols - він приймає імена або номера стовбців. Обрахуємо середнє для arr_delay і dep_delay, згрупуємо по origin, dest і month:
ans <- flights[,
lapply(.SD, mean),
by = .(origin, dest, month),
.SDcols = c("arr_delay", "dep_delay")]
ans
## origin dest month arr_delay dep_delay
## 1: JFK LAX 1 11.342956 20.521940
## 2: LGA PBI 1 23.000000 21.382143
## 3: EWR LAX 1 7.906494 18.745455
## 4: JFK MIA 1 20.454902 22.505882
## 5: JFK SEA 1 15.101449 27.253623
## ---
## 1913: EWR SAT 10 -15.500000 9.333333
## 1914: EWR BTV 10 -2.000000 -3.800000
## 1915: EWR ORF 10 6.833333 12.000000
## 1916: LGA DAL 10 -16.000000 -6.266667
## 1917: LGA CVG 10 -11.333333 -5.666667
Виберемо два перших рядка для кожного month
ans <- flights[, head(.SD, 2), by = month]
ans
## month year day dep_time dep_delay arr_time arr_delay cancelled carrier
## 1: 1 2014 1 914 14 1238 13 0 AA
## 2: 1 2014 1 1157 -3 1523 13 0 AA
## 3: 2 2014 1 859 -1 1226 1 0 AA
## 4: 2 2014 1 1155 -5 1528 3 0 AA
## 5: 3 2014 1 849 -11 1306 36 0 AA
## 6: 3 2014 1 1157 -3 1529 14 0 AA
## 7: 4 2014 1 1812 -8 1927 -23 0 MQ
## 8: 4 2014 1 1812 -8 1949 -11 0 MQ
## 9: 5 2014 1 1743 43 1955 5 0 AA
## 10: 5 2014 1 759 -1 1057 -38 0 AA
## 11: 6 2014 1 851 -9 1205 -5 0 AA
## 12: 6 2014 1 1220 -10 1522 -13 0 AA
## 13: 7 2014 1 727 -3 1043 -2 0 VX
## 14: 7 2014 1 904 -6 1201 -14 0 VX
## 15: 8 2014 1 822 -3 925 -5 0 AA
## 16: 8 2014 1 1549 19 2000 55 0 AA
## 17: 9 2014 1 851 -9 1144 -26 0 AA
## 18: 9 2014 1 1223 -7 1509 -21 0 AA
## 19: 10 2014 1 1412 -5 1551 -15 0 EV
## 20: 10 2014 1 1243 -7 1351 -21 0 EV
## tailnum flight origin dest air_time distance hour min
## 1: N338AA 1 JFK LAX 359 2475 9 14
## 2: N335AA 3 JFK LAX 363 2475 11 57
## 3: N783AA 1 JFK LAX 358 2475 8 59
## 4: N784AA 3 JFK LAX 358 2475 11 55
## 5: N784AA 1 JFK LAX 375 2475 8 49
## 6: N787AA 3 JFK LAX 368 2475 11 57
## 7: N514MQ 3486 LGA BNA 113 764 18 12
## 8: N543MQ 3501 LGA RDU 71 431 18 12
## 9: N3ELAA 45 JFK LAS 288 2248 17 43
## 10: N789AA 59 JFK SFO 330 2586 7 59
## 11: N787AA 1 JFK LAX 324 2475 8 51
## 12: N795AA 3 JFK LAX 329 2475 12 20
## 13: N361VA 11 JFK SFO 343 2586 7 27
## 14: N836VA 161 EWR LAX 320 2454 9 4
## 15: N3GDAA 84 JFK BOS 40 187 8 22
## 16: N783AA 85 JFK SFO 373 2586 15 49
## 17: N794AA 1 JFK LAX 325 2475 8 51
## 18: N798AA 3 JFK LAX 320 2475 12 23
## 19: N12567 4100 EWR MEM 140 946 14 12
## 20: N13538 4104 EWR BNA 109 748 12 43
.SD містить всі рядки для кожної групи month ми просто беремо перші два рядка із кожної групи head(.SD, 2) повертає data.table як list, тому не потірбно ставити .().
Можна об“єднати колонки:
DT[, .(val = c(a, b)), by = ID]
## ID val
## 1: a 1
## 2: a 2
## 3: a 3
## 4: a 7
## 5: a 8
## 6: a 9
## 7: b 4
## 8: b 5
## 9: b 10
## 10: b 11
## 11: c 6
## 12: c 12
DT[, .(val = list(c(a, b))), by = ID]
## ID val
## 1: a 1,2,3,7,8,9
## 2: b 4, 5,10,11
## 3: c 6,12
РЕЗЮМЕ
i:data.frame, за виключенням того, що не потірбно весь час використовувати символ $ - DT$a. Бо стовбці в data.table ведуть себе як змінні;data.table використовується більш швидка внутрішня реалізація фукнції order() (forder);j:data.table: DT[, .(colA, colB)];data.frame: DT[, c("colA", "colB"), with = FALSE];DT[, .(sum(colA), mean(colB))];і: DT[colA > 0, sum(colB)];by:keyby для групуючих стовбців, для їх подальшого впорядкування по групах;.SD(всі стовбці) і .SDcols(вибрані стовбці) для виконання базових фукнцій над стовбцями:
DT[, lapply(.SD, fun), by= ., .SDcols = .] - застосовує fun до всіх стовців, які вказані в .SDcols;DT[., head(.SD, 2), by = .] - виводить перші два рядки для кожної групи;DT[col > val, head(.SD, 1), by = .] - комбінація i, j, by.ВАЖЛИВО!!! Оскільки j-вираз повертає список, кожен елемент списку стає стовбцем підсумкової таблиці data.table.
# dplyr
f.1 <- flights %>%
mutate_each("factor", origin, tailnum) %>%
group_by(origin, tailnum) %>%
summarise(count = n(),
m.dist = mean(distance, na.rm = T),
m.dep.delay = mean(dep_delay, na.rm = T))
head(f.1)
## origin tailnum count m.dist m.dep.delay
## 1 JFK N338AA 72 2375.7083 13.54167
## 2 JFK N335AA 32 2502.7500 17.31250
## 3 JFK N327AA 7 2277.0000 21.85714
## 4 LGA N3EHAA 47 999.5957 37.29787
## 5 JFK N319AA 90 2337.1000 15.04444
## 6 EWR N3DEAA 6 1890.6667 -2.00000
# data.table
f.2 <- flights[,
.(count = .N,
m.dist = mean(distance, na.rm = T),
m.dep.delay = mean(dep_delay, na.rm = T)),
.(origin, tailnum)]
head(f.2)
## origin tailnum count m.dist m.dep.delay
## 1: JFK N338AA 72 2375.7083 13.54167
## 2: JFK N335AA 32 2502.7500 17.31250
## 3: JFK N327AA 7 2277.0000 21.85714
## 4: LGA N3EHAA 47 999.5957 37.29787
## 5: JFK N319AA 90 2337.1000 15.04444
## 6: EWR N3DEAA 6 1890.6667 -2.00000
g <- f.1 %>%
ggplot(aes(x = m.dist , y = m.dep.delay, colour = origin )) +
geom_point(alpha = 1/4) +
geom_smooth(method = "loess", se = F, size = 1) +
scale_y_continuous(limits = c(0, quantile(f.1$m.dep.delay, 0.99))) +
scale_x_continuous(limits = c(0, quantile(f.1$m.dist, 0.99))) +
scale_colour_manual(labels = c("EWR", "JFK", "LGA"), values = c("orange1", "royalblue2", "red4"))
g