Додавання/оновлення/видалення стовбців в data.table.

library(data.table)
library(dplyr)

address <- "https://raw.githubusercontent.com/wiki/arunsrinivasan/flights/NYCflights14/flights14.csv"

flights <- fread(address, showProgress = T)
dim(flights)
## [1] 253316     17

1. Семантика посилань

1.1 Оператор :=. Форма запису.

Форма LHS := RHS :

DT[, c("colA", "colB",...) := list(valA, valB,...)]

Функціональна форма :

DT[,:=(colA = valA, colB = valB,...)]

2. Додавання/оновлення/видалення стовбців за посиланням.

2.1 Додавання стовбців за посиланням.

Чи ми можемо додати стовбці швидкість і загальна затримка кожного рейсу в таблицю data.table - flights?

flights[, `:=`(speed = distance/(air_time/60),  # швидкість [км/год]
               delay = arr_delay + dep_delay)]  # затримка [хв]
head(flights)
##    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
## 3: 2014     1   1     1902         2     2224         9         0      AA
## 4: 2014     1   1      722        -8     1014       -26         0      AA
## 5: 2014     1   1     1347         2     1706         1         0      AA
## 6: 2014     1   1     1824         4     2145         0         0      AA
##    tailnum flight origin dest air_time distance hour min    speed delay
## 1:  N338AA      1    JFK  LAX      359     2475    9  14 413.6490    27
## 2:  N335AA      3    JFK  LAX      363     2475   11  57 409.0909    10
## 3:  N327AA     21    JFK  LAX      351     2475   19   2 423.0769    11
## 4:  N3EHAA     29    LGA  PBI      157     1035    7  22 395.5414   -34
## 5:  N319AA    117    JFK  LAX      350     2475   13  47 424.2857     3
## 6:  N3DEAA    119    EWR  LAX      339     2454   18  24 434.3363     4
#flights[, c("speed", "delay") := .(distance/(air_time/60), arr_delay + dep_delay)]
  • Ми не переприсвоїли результат flights;
  • Таблиця flights має два додаткових стовбця - додавання за посиланням;
  • Використали функціональну форму для додавання стовбців (LHS := RHS закоментована).

2.2 Оновлення деяких рядків за посиланням - часткове присвоєння за посиланням.

Подивимось на всі значення hours, які доступні в flights

flights[, sort(unique(hour))]
##  [1]  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22
## [24] 23 24

Замінемо 24 на 0:

flights[hour %in% c(0, 24), .(count = .N), by = hour]  # 0 = 710, 24 = 35
##    hour count
## 1:    0   710
## 2:   24    35
flights[hour == 24, hour := 0]  # заміна 24 на 0
flights[, sort(unique(hour))]   # 24 - відсутній
##  [1]  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22
## [24] 23
flights[hour %in% c(0, 24), .(count = .N), by = hour]  # 0 = 745 (710+35)
##    hour count
## 1:    0   745

2.3 Видалення стовбця за посиланням.

Видадити стовбець delay:

flights[, delay := NULL]
# flights[, c("delay") := NULL]
# flights[, `:=`(delay = NULL)]
head(flights)
##    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
## 3: 2014     1   1     1902         2     2224         9         0      AA
## 4: 2014     1   1      722        -8     1014       -26         0      AA
## 5: 2014     1   1     1347         2     1706         1         0      AA
## 6: 2014     1   1     1824         4     2145         0         0      AA
##    tailnum flight origin dest air_time distance hour min    speed
## 1:  N338AA      1    JFK  LAX      359     2475    9  14 413.6490
## 2:  N335AA      3    JFK  LAX      363     2475   11  57 409.0909
## 3:  N327AA     21    JFK  LAX      351     2475   19   2 423.0769
## 4:  N3EHAA     29    LGA  PBI      157     1035    7  22 395.5414
## 5:  N319AA    117    JFK  LAX      350     2475   13  47 424.2857
## 6:  N3DEAA    119    EWR  LAX      339     2454   18  24 434.3363

2.4 Використання := разом із by.

Як додати новий стовбець, який має максимальну швидкість для кожної пари origin, dest?

flights[, `:=`(max.speed = max(speed)), by = .(origin, dest)]
head(flights)
##    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
## 3: 2014     1   1     1902         2     2224         9         0      AA
## 4: 2014     1   1      722        -8     1014       -26         0      AA
## 5: 2014     1   1     1347         2     1706         1         0      AA
## 6: 2014     1   1     1824         4     2145         0         0      AA
##    tailnum flight origin dest air_time distance hour min    speed
## 1:  N338AA      1    JFK  LAX      359     2475    9  14 413.6490
## 2:  N335AA      3    JFK  LAX      363     2475   11  57 409.0909
## 3:  N327AA     21    JFK  LAX      351     2475   19   2 423.0769
## 4:  N3EHAA     29    LGA  PBI      157     1035    7  22 395.5414
## 5:  N319AA    117    JFK  LAX      350     2475   13  47 424.2857
## 6:  N3DEAA    119    EWR  LAX      339     2454   18  24 434.3363
##    max.speed
## 1:  526.5957
## 2:  526.5957
## 3:  526.5957
## 4:  517.5000
## 5:  526.5957
## 6:  518.4507

2.5 Множинні стовбці і :=.

Як додати ще два стовбця, розрахувавши max() для dep_delay і arr_delay для кожного місяця, використовуючі .SD?

in.col <- c("dep_delay", "arr_delay")
out.col <- c("max_dep_delay", "max_arr_delay")

flights[, 
        c(out.col) := lapply(.SD, max) , 
        by = month, 
        .SDcols = in.col]
head(flights)
##    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
## 3: 2014     1   1     1902         2     2224         9         0      AA
## 4: 2014     1   1      722        -8     1014       -26         0      AA
## 5: 2014     1   1     1347         2     1706         1         0      AA
## 6: 2014     1   1     1824         4     2145         0         0      AA
##    tailnum flight origin dest air_time distance hour min    speed
## 1:  N338AA      1    JFK  LAX      359     2475    9  14 413.6490
## 2:  N335AA      3    JFK  LAX      363     2475   11  57 409.0909
## 3:  N327AA     21    JFK  LAX      351     2475   19   2 423.0769
## 4:  N3EHAA     29    LGA  PBI      157     1035    7  22 395.5414
## 5:  N319AA    117    JFK  LAX      350     2475   13  47 424.2857
## 6:  N3DEAA    119    EWR  LAX      339     2454   18  24 434.3363
##    max.speed max_dep_delay max_arr_delay
## 1:  526.5957           973           996
## 2:  526.5957           973           996
## 3:  526.5957           973           996
## 4:  517.5000           973           996
## 5:  526.5957           973           996
## 6:  518.4507           973           996

Якщо поставити out.cols := lapply(.SD, max) (без c()), то створиться стовбець із назвою out.cols.

Видалимо змінні, які були створені: speed, max.speed, max_dep_delay, max_arr_delay:

# glimpse(flights)
del.cols <- c("speed", "max.speed", "max_dep_delay", "max_arr_delay")
flights[, c(del.cols) := NULL]
head(flights)
##    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
## 3: 2014     1   1     1902         2     2224         9         0      AA
## 4: 2014     1   1      722        -8     1014       -26         0      AA
## 5: 2014     1   1     1347         2     1706         1         0      AA
## 6: 2014     1   1     1824         4     2145         0         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
## 3:  N327AA     21    JFK  LAX      351     2475   19   2
## 4:  N3EHAA     29    LGA  PBI      157     1035    7  22
## 5:  N319AA    117    JFK  LAX      350     2475   13  47
## 6:  N3DEAA    119    EWR  LAX      339     2454   18  24

3. := i copy().

3.1 Використання оператора := заради його побічного ефекту.

Напишемо функцію, яка визначає максимальну швидкість по кожному місяцю і додає до вхідної таблиці колонку speed

foo <- function(DT) {
  DT[, speed := distance/(arr_time/60)]
  DT[, .(max.speed = max(speed)), by = month]
}
foo(flights)
##     month max.speed
##  1:     1    129180
##  2:     2    155160
##  3:     3    155160
##  4:     4    155160
##  5:     5    155160
##  6:     6    153900
##  7:     7    155160
##  8:     8    153900
##  9:     9    147240
## 10:    10    155160
head(flights)
##    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
## 3: 2014     1   1     1902         2     2224         9         0      AA
## 4: 2014     1   1      722        -8     1014       -26         0      AA
## 5: 2014     1   1     1347         2     1706         1         0      AA
## 6: 2014     1   1     1824         4     2145         0         0      AA
##    tailnum flight origin dest air_time distance hour min     speed
## 1:  N338AA      1    JFK  LAX      359     2475    9  14 119.95153
## 2:  N335AA      3    JFK  LAX      363     2475   11  57  97.50492
## 3:  N327AA     21    JFK  LAX      351     2475   19   2  66.77158
## 4:  N3EHAA     29    LGA  PBI      157     1035    7  22  61.24260
## 5:  N319AA    117    JFK  LAX      350     2475   13  47  87.04572
## 6:  N3DEAA    119    EWR  LAX      339     2454   18  24  68.64336

До flights додалась колонка speed.

3.2 Функція copy().

Якщо потрібно, щоб автоматично не оновлювалась вхідна таблиця, то потрібно використовувати функцію copy(). Функція copy() створює глибинну копію об“єкта, тому будь-які зміни, які відбуваються при використанні оператора := не відображаються на ній.

Видалимо колонку speed:

flights[, speed := NULL]
head(flights)
##    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
## 3: 2014     1   1     1902         2     2224         9         0      AA
## 4: 2014     1   1      722        -8     1014       -26         0      AA
## 5: 2014     1   1     1347         2     1706         1         0      AA
## 6: 2014     1   1     1824         4     2145         0         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
## 3:  N327AA     21    JFK  LAX      351     2475   19   2
## 4:  N3EHAA     29    LGA  PBI      157     1035    7  22
## 5:  N319AA    117    JFK  LAX      350     2475   13  47
## 6:  N3DEAA    119    EWR  LAX      339     2454   18  24

Перепишемо функцію, використовуючі copy():

foo <- function(DT) {
  DT <- copy(DT)  # зробили глибинну копію
  DT[, speed := distance/(arr_time/60)]
  DT[, .(max.speed = max(speed)), by = month]
}
ans <- foo(flights)
head(ans)
##    month max.speed
## 1:     1    129180
## 2:     2    155160
## 3:     3    155160
## 4:     4    155160
## 5:     5    155160
## 6:     6    153900
head(flights)
##    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
## 3: 2014     1   1     1902         2     2224         9         0      AA
## 4: 2014     1   1      722        -8     1014       -26         0      AA
## 5: 2014     1   1     1347         2     1706         1         0      AA
## 6: 2014     1   1     1824         4     2145         0         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
## 3:  N327AA     21    JFK  LAX      351     2475   19   2
## 4:  N3EHAA     29    LGA  PBI      157     1035    7  22
## 5:  N319AA    117    JFK  LAX      350     2475   13  47
## 6:  N3DEAA    119    EWR  LAX      339     2454   18  24

Колонка speed в flights не створилась

Якщо, наприклад, буде створена змінна із іменами стовбців таблиці data.table - DT_n = names(DT), а потім оновимо стовбці за посиланням, то DT_n також зміниться:

DT <- data.table(x=1, y=2)
DT
##    x y
## 1: 1 2
DT_n <- names(DT)
DT_n
## [1] "x" "y"
DT[, z := 3]
DT_n
## [1] "x" "y" "z"
DT_n <- copy(names(DT))
DT[, w := 4]
DT_n
## [1] "x" "y" "z"