На прошлом занятии мы поговорили о том, откуда можно взять данные, и как их импортировать. Но почти всегда данные приходят не в том виде, в котором нам хотелось бы. Поэтому перед тем как приступать к визуализации или построению модели, нужно обработать наши данные. В этом нам поможет пакет dplyr
, который входит в библиотеку tidyverse
.
Мы рассмотрим основные функции этого пакета:
filter
arrange
select
mutate
summarize
group_by
Функции из этого пакеты мы будем использовать на датасете flights
, который находится в пакете nycflights13
.В этом датасете содержится информация о всех авиарейсах аэропортов Нью-Йорка, совершенных в 2013 году. Описание датасета можно получить выполнив команду ?flights
.
Давайте подгрузим наши пакеты .
# install.packages('dplyr')
# install.packages('nycflights13')
library('dplyr')
library('nycflights13')
Посмотрим на наш датасет.
## Observations: 336,776
## Variables: 19
## $ year <int> 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2…
## $ month <int> 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…
## $ dep_time <int> 517, 533, 542, 544, 554, 554, 555, 557, 557, 558,…
## $ sched_dep_time <int> 515, 529, 540, 545, 600, 558, 600, 600, 600, 600,…
## $ dep_delay <dbl> 2, 4, 2, -1, -6, -4, -5, -3, -3, -2, -2, -2, -2, …
## $ arr_time <int> 830, 850, 923, 1004, 812, 740, 913, 709, 838, 753…
## $ sched_arr_time <int> 819, 830, 850, 1022, 837, 728, 854, 723, 846, 745…
## $ arr_delay <dbl> 11, 20, 33, -18, -25, 12, 19, -14, -8, 8, -2, -3,…
## $ carrier <chr> "UA", "UA", "AA", "B6", "DL", "UA", "B6", "EV", "…
## $ flight <int> 1545, 1714, 1141, 725, 461, 1696, 507, 5708, 79, …
## $ tailnum <chr> "N14228", "N24211", "N619AA", "N804JB", "N668DN",…
## $ origin <chr> "EWR", "LGA", "JFK", "JFK", "LGA", "EWR", "EWR", …
## $ dest <chr> "IAH", "IAH", "MIA", "BQN", "ATL", "ORD", "FLL", …
## $ air_time <dbl> 227, 227, 160, 183, 116, 150, 158, 53, 140, 138, …
## $ distance <dbl> 1400, 1416, 1089, 1576, 762, 719, 1065, 229, 944,…
## $ hour <dbl> 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6…
## $ minute <dbl> 15, 29, 40, 45, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
## $ time_hour <dttm> 2013-01-01 05:00:00, 2013-01-01 05:00:00, 2013-0…
Значение некоторых переменных:
year
, month
, day
– дата отправленияdep_time
, arr_time
– aактическое время отправления и прибытия (формат HHMM или HMM)sched_dep_time
, sched_arr_time
– запланированное время отправления и прибытия (формат HHMM или HMM)dep_delay
, arr_delay
– задержка вылета и прилет (в минутах)carrier
– сокращенное название авиакомпании (в датасете airlines
можно найти полное название)flight
– номер рейсаtailnum
– номер самолета (в датасете planes
можно узнать больше о самолете)origin
, dest
– сокращенное название аэропорта отбытия и прибытияair_time
– общее время в воздухе (в минутах)distance
– дистанция между аэропортами в миляхА теперь начнем изучать возможности пакета dplyr
!
С помощью функции filter
вы можете отбирать наблюдения по каким-то критериям. Первым аргументом функции является название датасета (df). Последующие аргументы это логические выражения, которые обеспечивают отбор (фильтрацию). Давайте попробуем использовать эту функцию на практике.
## # A tibble: 27,004 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 1 517 515 2 830
## 2 2013 1 1 533 529 4 850
## 3 2013 1 1 542 540 2 923
## 4 2013 1 1 544 545 -1 1004
## 5 2013 1 1 554 600 -6 812
## 6 2013 1 1 554 558 -4 740
## 7 2013 1 1 555 600 -5 913
## 8 2013 1 1 557 600 -3 709
## 9 2013 1 1 557 600 -3 838
## 10 2013 1 1 558 600 -2 753
## # … with 26,994 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
Данная функция на выходе выдаёт df c авиарейсами, которые были совершены в январе. Наше логическое выражение строится следующим образом: выбираем название колонки и сравниваем его с какими-либо значения. Важно отметить, что названия колонок не находятся в кавычках.
Чтобы эффективно пользоваться данной функцией, нужно вспомнить операторы сравнения:
>
– больше<
– меньше>=
– больше или равно<=
– меньше или равно==
– равно!=
– не равноВы можете смело использовать их для составления логических выражений. Помним, что один знак равно (=
) – это оператор присваивания, а два знака равно (==
) – оператор сравнения.
Функция не поменяла датасет flights
. Если вы хотите запомнить результат, то вам нужно присвоить его какой-нибудь переменной.
Помним, что при сравнении могут возникнуть некоторые проблемы, связанные с точностью.
Чтобы избежать такого рода проблемы лучше использовать функцию near
вместо ==
.
Если передавать функции filter
несколько аргументов, то мы увидим только те наблюдения, которые удовлетворяют всем условиям, то есть будет использоваться логический оператор И
.
## # A tibble: 842 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 1 517 515 2 830
## 2 2013 1 1 533 529 4 850
## 3 2013 1 1 542 540 2 923
## 4 2013 1 1 544 545 -1 1004
## 5 2013 1 1 554 600 -6 812
## 6 2013 1 1 554 558 -4 740
## 7 2013 1 1 555 600 -5 913
## 8 2013 1 1 557 600 -3 709
## 9 2013 1 1 557 600 -3 838
## 10 2013 1 1 558 600 -2 753
## # … with 832 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
Давайте вспомним основные логические операторы:
И
– наблюдения, которые удовлетворяют всем условиям (&
).ИЛИ
– наблюдения, которые удовлетворяют хотя бы одному условию (|
).НЕ
– наблюдения, которые не удовлетворяют данному условию (!
).XOR
– наблюдения, которые не удовлетворяют обоим условиям, то есть дополнение к И
(xor()
).НЕЛЬЗЯ использовать &&
и ||
, которые мы привыкли использовать ранее.
Посмотрим как ими можно пользоваться.
## # A tibble: 57,039 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 5 1 9 1655 434 308
## 2 2013 5 1 451 500 -9 641
## 3 2013 5 1 537 540 -3 836
## 4 2013 5 1 544 545 -1 818
## 5 2013 5 1 548 600 -12 831
## 6 2013 5 1 549 600 -11 804
## 7 2013 5 1 553 600 -7 700
## 8 2013 5 1 553 600 -7 655
## 9 2013 5 1 554 600 -6 731
## 10 2013 5 1 554 600 -6 707
## # … with 57,029 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
Данный запрос выведет все авиарейсы за май и июнь. Важно понимать, что записывать запрос таким образом: filter(flights, month == 5|6)
НЕЛЬЗЯ!.
Когда значений для одного столбца достаточно много, то не очень удобно записывать все это для каждого значения. На помощь приходит выражение %in%
. Его можно использовать как в коде, так и в работе с данными. Ниже можно увидеть два одинаковых выражения, но второе намного приятнее.
filter(flights, month == 5, month == 6, month == 8, month == 12)
filter(flights, month %in% c(5, 6, 8, 12))
Старайтесь не создавать сложные запросы.
## # A tibble: 316,050 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 1 517 515 2 830
## 2 2013 1 1 533 529 4 850
## 3 2013 1 1 542 540 2 923
## 4 2013 1 1 544 545 -1 1004
## 5 2013 1 1 554 600 -6 812
## 6 2013 1 1 554 558 -4 740
## 7 2013 1 1 555 600 -5 913
## 8 2013 1 1 557 600 -3 709
## 9 2013 1 1 557 600 -3 838
## 10 2013 1 1 558 600 -2 753
## # … with 316,040 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
Данный запрос выводит все авиарейсы с зарержкой не более 2 часов (как по прибытию, так и по отправке). Запрос выглядит очень сложно. Старайтесь этого избегать. Например, если вспомнить законы де Моргана из дискретной математики, то можно его упростить.
## # A tibble: 316,050 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 1 517 515 2 830
## 2 2013 1 1 533 529 4 850
## 3 2013 1 1 542 540 2 923
## 4 2013 1 1 544 545 -1 1004
## 5 2013 1 1 554 600 -6 812
## 6 2013 1 1 554 558 -4 740
## 7 2013 1 1 555 600 -5 913
## 8 2013 1 1 557 600 -3 709
## 9 2013 1 1 557 600 -3 838
## 10 2013 1 1 558 600 -2 753
## # … with 316,040 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
Важно также разобраться с отсутствующими значениями (NA
). Чтобы проверить является ли значение равным NA
, нужно использовать функцию is.na
. C помощью этой функции можно убрать наблюдения, по которым у нас нет данных.
## # A tibble: 327,346 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 1 517 515 2 830
## 2 2013 1 1 533 529 4 850
## 3 2013 1 1 542 540 2 923
## 4 2013 1 1 544 545 -1 1004
## 5 2013 1 1 554 600 -6 812
## 6 2013 1 1 554 558 -4 740
## 7 2013 1 1 555 600 -5 913
## 8 2013 1 1 557 600 -3 709
## 9 2013 1 1 557 600 -3 838
## 10 2013 1 1 558 600 -2 753
## # … with 327,336 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
С помощью функции arrange
вы можете отсортировать ваш датафрейм. Первым аргументом функции является название датасета (df). Последующие аргументы это названия столбцов, по которым идет сортировка.
## # A tibble: 336,776 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 1 517 515 2 830
## 2 2013 1 1 533 529 4 850
## 3 2013 1 1 542 540 2 923
## 4 2013 1 1 544 545 -1 1004
## 5 2013 1 1 554 600 -6 812
## 6 2013 1 1 554 558 -4 740
## 7 2013 1 1 555 600 -5 913
## 8 2013 1 1 557 600 -3 709
## 9 2013 1 1 557 600 -3 838
## 10 2013 1 1 558 600 -2 753
## # … with 336,766 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
С помощью такого запроса мы отсортировали сначала года, потом месяцы для каждого года, а потом дни в каждом месяце. Порядок аргументов здесь очень важен! Можно убедиться на примере ниже.
## # A tibble: 336,776 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 1 517 515 2 830
## 2 2013 1 1 533 529 4 850
## 3 2013 1 1 542 540 2 923
## 4 2013 1 1 544 545 -1 1004
## 5 2013 1 1 554 600 -6 812
## 6 2013 1 1 554 558 -4 740
## 7 2013 1 1 555 600 -5 913
## 8 2013 1 1 557 600 -3 709
## 9 2013 1 1 557 600 -3 838
## 10 2013 1 1 558 600 -2 753
## # … with 336,766 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
Если вы хотите отсортировать по убыванию, то можете использовать функцию desc
.
## # A tibble: 336,776 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 1 517 515 2 830
## 2 2013 1 1 533 529 4 850
## 3 2013 1 1 542 540 2 923
## 4 2013 1 1 544 545 -1 1004
## 5 2013 1 1 554 600 -6 812
## 6 2013 1 1 554 558 -4 740
## 7 2013 1 1 555 600 -5 913
## 8 2013 1 1 557 600 -3 709
## 9 2013 1 1 557 600 -3 838
## 10 2013 1 1 558 600 -2 753
## # … with 336,766 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
Важно знать, что отсутствующие значения (NA
) будут находиться в самом конце после сортировки.
Часто бывает, что в данных очень много переменных, но вам нужны только некоторые. С помощью функции select
вы можете сделать это. Первым аргументом функции является название датасета (df). Последующие аргументы это переменные (название стобцов), которые вам нужны.
С помощью запроса ниже мы выбрали переменные:
year
month
day
## # A tibble: 336,776 x 3
## year month day
## <int> <int> <int>
## 1 2013 1 1
## 2 2013 1 1
## 3 2013 1 1
## 4 2013 1 1
## 5 2013 1 1
## 6 2013 1 1
## 7 2013 1 1
## 8 2013 1 1
## 9 2013 1 1
## 10 2013 1 1
## # … with 336,766 more rows
А с помощью такого мы выбрали все переменные, которые находятся между year
и day
.
## # A tibble: 336,776 x 3
## year month day
## <int> <int> <int>
## 1 2013 1 1
## 2 2013 1 1
## 3 2013 1 1
## 4 2013 1 1
## 5 2013 1 1
## 6 2013 1 1
## 7 2013 1 1
## 8 2013 1 1
## 9 2013 1 1
## 10 2013 1 1
## # … with 336,766 more rows
Аналогичный запрос, но с индексами столбцов.
## # A tibble: 336,776 x 3
## year month day
## <int> <int> <int>
## 1 2013 1 1
## 2 2013 1 1
## 3 2013 1 1
## 4 2013 1 1
## 5 2013 1 1
## 6 2013 1 1
## 7 2013 1 1
## 8 2013 1 1
## 9 2013 1 1
## 10 2013 1 1
## # … with 336,766 more rows
Если вы хотите увидеть все столбцы за исключением каких-то, то можно воспользоваться знаком -
.
## # A tibble: 336,776 x 16
## dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay
## <int> <int> <dbl> <int> <int> <dbl>
## 1 517 515 2 830 819 11
## 2 533 529 4 850 830 20
## 3 542 540 2 923 850 33
## 4 544 545 -1 1004 1022 -18
## 5 554 600 -6 812 837 -25
## 6 554 558 -4 740 728 12
## 7 555 600 -5 913 854 19
## 8 557 600 -3 709 723 -14
## 9 557 600 -3 838 846 -8
## 10 558 600 -2 753 745 8
## # … with 336,766 more rows, and 10 more variables: carrier <chr>,
## # flight <int>, tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>,
## # distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
Такие запросы можно комбинировать. Можно взять первые десять столбцов за исключением 2.
## # A tibble: 336,776 x 9
## year day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 1 517 515 2 830 819
## 2 2013 1 533 529 4 850 830
## 3 2013 1 542 540 2 923 850
## 4 2013 1 544 545 -1 1004 1022
## 5 2013 1 554 600 -6 812 837
## 6 2013 1 554 558 -4 740 728
## 7 2013 1 555 600 -5 913 854
## 8 2013 1 557 600 -3 709 723
## 9 2013 1 557 600 -3 838 846
## 10 2013 1 558 600 -2 753 745
## # … with 336,766 more rows, and 2 more variables: arr_delay <dbl>,
## # carrier <chr>
Когда переменных очень много, то такой способ становиться неудобным. На помощь приходят вспомогательные функции:
starts_with('abc')
– отбирает столбцы, которые начинаются c abc.ends_with('xyz')
– отбирает столбцы, которые заканчиваются на xyz.contains('ijk')
– обирает столбцы, которые содержат последовательность символов ijk.matches('(.)\\1')
– обирает столбцы, которые удовлетворяют регулярному выражению.num_range("x", 1:5)
– отбирает столбцы с названием x1
, x2
, x3
, x4
, x5
.one_of(vars)
– выбирает столбцы, название которых находится в векторе vars
. Если какого-то столбца нет, то выдаст предупреждение, но не ошибку(если бы мы не использовали функцию).Более подробно об этих и других вспомогательных функциях можно узнать с помощью команды ?select_helpers
.
Давайте попробуем их применить. Допустим нам нужные только данные, которые связаны с прилётом.
## # A tibble: 336,776 x 4
## arr_time sched_arr_time arr_delay carrier
## <int> <int> <dbl> <chr>
## 1 830 819 11 UA
## 2 850 830 20 UA
## 3 923 850 33 AA
## 4 1004 1022 -18 B6
## 5 812 837 -25 DL
## 6 740 728 12 UA
## 7 913 854 19 B6
## 8 709 723 -14 EV
## 9 838 846 -8 B6
## 10 753 745 8 AA
## # … with 336,766 more rows
Появился лишний столбец carrier
, но нам уже проще работать с таким датасетом (df).
Есть еще одна вспомогательная everything()
. Она помогает перенести некоторые переменные в начало датафрейма. Это бывает удобно, если вы хотите сохранить переменные, но изменить их порядок. Давайте перенесем переменные air_time
и time_hour
вперёд, а остальные переменные пойдут за ними.
## # A tibble: 336,776 x 19
## air_time time_hour year month day dep_time sched_dep_time
## <dbl> <dttm> <int> <int> <int> <int> <int>
## 1 227 2013-01-01 05:00:00 2013 1 1 517 515
## 2 227 2013-01-01 05:00:00 2013 1 1 533 529
## 3 160 2013-01-01 05:00:00 2013 1 1 542 540
## 4 183 2013-01-01 05:00:00 2013 1 1 544 545
## 5 116 2013-01-01 06:00:00 2013 1 1 554 600
## 6 150 2013-01-01 05:00:00 2013 1 1 554 558
## 7 158 2013-01-01 06:00:00 2013 1 1 555 600
## 8 53 2013-01-01 06:00:00 2013 1 1 557 600
## 9 140 2013-01-01 06:00:00 2013 1 1 557 600
## 10 138 2013-01-01 06:00:00 2013 1 1 558 600
## # … with 336,766 more rows, and 12 more variables: dep_delay <dbl>,
## # arr_time <int>, sched_arr_time <int>, arr_delay <dbl>, carrier <chr>,
## # flight <int>, tailnum <chr>, origin <chr>, dest <chr>, distance <dbl>,
## # hour <dbl>, minute <dbl>
С помощью функции select
можно переименовать переменные, но при этом останутся только те переменные, которые вы переименовали.
## # A tibble: 336,776 x 1
## Год
## <int>
## 1 2013
## 2 2013
## 3 2013
## 4 2013
## 5 2013
## 6 2013
## 7 2013
## 8 2013
## 9 2013
## 10 2013
## # … with 336,766 more rows
Для того, чтобы переименовать какой-то столбец, но оставить все остальные, можно использовать функцию rename
.
## # A tibble: 336,776 x 19
## Год month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 1 517 515 2 830
## 2 2013 1 1 533 529 4 850
## 3 2013 1 1 542 540 2 923
## 4 2013 1 1 544 545 -1 1004
## 5 2013 1 1 554 600 -6 812
## 6 2013 1 1 554 558 -4 740
## 7 2013 1 1 555 600 -5 913
## 8 2013 1 1 557 600 -3 709
## 9 2013 1 1 557 600 -3 838
## 10 2013 1 1 558 600 -2 753
## # … with 336,766 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
С помощью функции mutate
вы сможете создавать новые переменные, основанные на уже существующих. Первым аргументом функции является название датасета (df). Последующие аргументы выглядят следующим образом:
название новой переменной = операции с существующими переменными
Новые переменные добавляются в конец df. Поэтому давайте уменьшим наш df, чтобы мы могли увидеть новые переменные.
Давайте создадим переменную speed
. Она будет показывать среднюю скорость самолёта.
## # A tibble: 336,776 x 6
## year month day distance air_time speed_ml
## <int> <int> <int> <dbl> <dbl> <dbl>
## 1 2013 1 1 1400 227 370.
## 2 2013 1 1 1416 227 374.
## 3 2013 1 1 1089 160 408.
## 4 2013 1 1 1576 183 517.
## 5 2013 1 1 762 116 394.
## 6 2013 1 1 719 150 288.
## 7 2013 1 1 1065 158 404.
## 8 2013 1 1 229 53 259.
## 9 2013 1 1 944 140 405.
## 10 2013 1 1 733 138 319.
## # … with 336,766 more rows
Умножаем на 60, так как время дано в минутах. Данная скорость мили/час. На только что созданные переменные можно сразу же ссылаться. Давайте найдем скорость км/час.
## # A tibble: 336,776 x 7
## year month day distance air_time speed_ml speed_km
## <int> <int> <int> <dbl> <dbl> <dbl> <dbl>
## 1 2013 1 1 1400 227 370. 596.
## 2 2013 1 1 1416 227 374. 603.
## 3 2013 1 1 1089 160 408. 657.
## 4 2013 1 1 1576 183 517. 832.
## 5 2013 1 1 762 116 394. 635.
## 6 2013 1 1 719 150 288. 463.
## 7 2013 1 1 1065 158 404. 651.
## 8 2013 1 1 229 53 259. 417.
## 9 2013 1 1 944 140 405. 651.
## 10 2013 1 1 733 138 319. 513.
## # … with 336,766 more rows
Если вы хотите выделить только те переменные, которые только создали вы можете использовать функцию transmute
.
## # A tibble: 336,776 x 2
## speed_ml speed_km
## <dbl> <dbl>
## 1 370. 596.
## 2 374. 603.
## 3 408. 657.
## 4 517. 832.
## 5 394. 635.
## 6 288. 463.
## 7 404. 651.
## 8 259. 417.
## 9 405. 651.
## 10 319. 513.
## # … with 336,766 more rows
Существует много функций для создания новых переменных. Все они должны быть векторизованы. Ознакомимся с основынми функциями.
Арифметические операторы:
+
– сложение-
– вычитаение*
– умножение/
– деление^
– возведение в степень%/%
– целочисленное деление%%
– взятие остатка## # A tibble: 336,776 x 6
## year month day distance air_time `air_time/60`
## <int> <int> <int> <dbl> <dbl> <dbl>
## 1 2013 1 1 1400 227 3.78
## 2 2013 1 1 1416 227 3.78
## 3 2013 1 1 1089 160 2.67
## 4 2013 1 1 1576 183 3.05
## 5 2013 1 1 762 116 1.93
## 6 2013 1 1 719 150 2.5
## 7 2013 1 1 1065 158 2.63
## 8 2013 1 1 229 53 0.883
## 9 2013 1 1 944 140 2.33
## 10 2013 1 1 733 138 2.3
## # … with 336,766 more rows
В наборе данных flights
из столбца dep_time
можно извлечь часы и минуты.
## # A tibble: 336,776 x 3
## dep_time hour minute
## <int> <dbl> <dbl>
## 1 517 5 17
## 2 533 5 33
## 3 542 5 42
## 4 544 5 44
## 5 554 5 54
## 6 554 5 54
## 7 555 5 55
## 8 557 5 57
## 9 557 5 57
## 10 558 5 58
## # … with 336,766 more rows
Логарифмические операторы:
log()
– натуральный логарифмlog2()
– логарифм с основанием 2log10()
– логарифм с основанием 10Полезно использовать, когда данные охватывают огромный диапозон.
## # A tibble: 336,776 x 2
## distance log_distance
## <dbl> <dbl>
## 1 1400 7.24
## 2 1416 7.26
## 3 1089 6.99
## 4 1576 7.36
## 5 762 6.64
## 6 719 6.58
## 7 1065 6.97
## 8 229 5.43
## 9 944 6.85
## 10 733 6.60
## # … with 336,766 more rows
Смещения:
lead()
– ссылка на следующие значениеlag()
– ссылка на предыдущее значение## [1] NA 1 2 3 4 5 6 7 8 9
## [1] 2 3 4 5 6 7 8 9 10 NA
Удобно находить доли x - lag(x)
или определять изменилось ли значение x != lag(x)
. Удобно использовать с функцией group_by
, о которой поговорим далее.
Кумулятативные и скользящие агрегаты:
cumsum()
cumprod()
cummin()
cummax()
cummean()
## [1] 1 2 3 4 5 6 7 8 9 10
## [1] 1 3 6 10 15 21 28 36 45 55
## [1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5
Если вы хотите находить скользящие в пределах “окна”, то используйте пакет RcppRoll
.
Логические операторы сравнения:
>
– больше<
– меньше>=
– больше или равно<=
– меньше или равно==
– равно!=
– не равно## # A tibble: 336,776 x 6
## year month day distance air_time `air_time > 120`
## <int> <int> <int> <dbl> <dbl> <lgl>
## 1 2013 1 1 1400 227 TRUE
## 2 2013 1 1 1416 227 TRUE
## 3 2013 1 1 1089 160 TRUE
## 4 2013 1 1 1576 183 TRUE
## 5 2013 1 1 762 116 FALSE
## 6 2013 1 1 719 150 TRUE
## 7 2013 1 1 1065 158 TRUE
## 8 2013 1 1 229 53 FALSE
## 9 2013 1 1 944 140 TRUE
## 10 2013 1 1 733 138 TRUE
## # … with 336,766 more rows
Функция summarize
позволяет свертывать набор данных в одну строчку. Например найти среднее по столбцу dep_delay
.
## # A tibble: 1 x 1
## delay
## <dbl>
## 1 12.6
Также можно найти:
sum
– суммуmin
– минимальное значениеmax
– максимальное значениеmean
– среднее значениеvar
– дисперсиюmedian
– медиануsd
– среднеквадратическое отклонениеIQR
– межквартильный размахmad
– медианное абсолютное отклонениеquantile(x, 0.25)
– определенный квантиль(в данном примере 25%)n()
– количество элементов(можно использовать функцию count
)sum(!is.na(x))
– количество элементов не равных NA
n_distinct
– количество уникальных элементовsum(x > 10)
– количество элементов больше 10mean(x == 0)
– доля элементов равных 0 от общего количестваЭта функция не очень полезна, если используется не в связке с функцией group_by
. Данная функция группирует данные по заданным переменным. Допустим мы хотим найти среднее значение задержки вылета для каждого дня.
by_day <- group_by(flights, year, month, day)
summarize(by_day, delay = mean(dep_delay, na.rm = TRUE))
## # A tibble: 365 x 4
## # Groups: year, month [12]
## year month day delay
## <int> <int> <int> <dbl>
## 1 2013 1 1 11.5
## 2 2013 1 2 13.9
## 3 2013 1 3 11.0
## 4 2013 1 4 8.95
## 5 2013 1 5 5.73
## 6 2013 1 6 7.15
## 7 2013 1 7 5.42
## 8 2013 1 8 2.55
## 9 2013 1 9 2.28
## 10 2013 1 10 2.84
## # … with 355 more rows
Можно устранить группирование с помощью функции ungroup
.
%>%
)Так называемый “канал” облегчает написание кода. Давайте поймем как он работает на простом примере. Предположим у нас есть массив x
и мы хотим найти его среднее. Мы бы сделали это так.
## [1] 5.5
Но эту же операцию можно проделать с помощью pipe (%>%
).
## [1] 5.5
Можно задаться вопросом, зачем делать так, а не как раньше? Давайте представим, что нам дан массив. Нам нужно возвести все элементы в квадрат, найти среднее, а потом взять от него корень. Это можно сделать 2 способами.
У каждого варианта есть свои минусы. В первом случае кода очень много , и мы создаем очень много переменных. Во втором случае код короткий, но читать его очень неудобно. Все эти операции можно было сделать с помощью pipe(%>%
).
## [1] 6.204837
Данный код убирает эти две проблемы. Его можно читать в повелительном наклонении слева направо. Заметим, что он заменяет первый аргумент функций. Это очень удобно использовать в пакете dplyr
, так как первым аргументом функций является df.
Предположим, что мы проводим какие-то манимуляции с нашими данными, то есть применяем функции, которые мы изучили. К примеру выберем столбцы year
, month
, day
и dep_delay
. Отберем наблюдения где dep_delay > 0
. Сгруппируем их по дням и найдем для каждого среднее значение dep_delay
.
flights %>% select(year, month, day, dep_delay) %>%
filter(dep_delay > 0) %>%
group_by(year, month, day) %>%
summarize(mean_dep_delay = mean(dep_delay, na.rm = TRUE))
## # A tibble: 365 x 4
## # Groups: year, month [12]
## year month day mean_dep_delay
## <int> <int> <int> <dbl>
## 1 2013 1 1 32.7
## 2 2013 1 2 32.6
## 3 2013 1 3 28.5
## 4 2013 1 4 26.2
## 5 2013 1 5 21.8
## 6 2013 1 6 22.0
## 7 2013 1 7 26.2
## 8 2013 1 8 21.2
## 9 2013 1 9 26.4
## 10 2013 1 10 32.6
## # … with 355 more rows
count()
=group_by()
+n()
Найдем количество перелетов за каждый день.
## # A tibble: 365 x 4
## # Groups: year, month [12]
## year month day n
## <int> <int> <int> <int>
## 1 2013 1 1 842
## 2 2013 1 2 943
## 3 2013 1 3 914
## 4 2013 1 4 915
## 5 2013 1 5 720
## 6 2013 1 6 832
## 7 2013 1 7 933
## 8 2013 1 8 899
## 9 2013 1 9 902
## 10 2013 1 10 932
## # … with 355 more rows
Это можно было сделать короче с помощью count
.
## # A tibble: 365 x 4
## year month day n
## <int> <int> <int> <int>
## 1 2013 1 1 842
## 2 2013 1 2 943
## 3 2013 1 3 914
## 4 2013 1 4 915
## 5 2013 1 5 720
## 6 2013 1 6 832
## 7 2013 1 7 933
## 8 2013 1 8 899
## 9 2013 1 9 902
## 10 2013 1 10 932
## # … with 355 more rows
В count
есть аргумент sort
, который может отсортировать значения по убыванию.
## # A tibble: 365 x 4
## year month day n
## <int> <int> <int> <int>
## 1 2013 11 27 1014
## 2 2013 7 11 1006
## 3 2013 7 8 1004
## 4 2013 7 10 1004
## 5 2013 12 2 1004
## 6 2013 7 18 1003
## 7 2013 7 25 1003
## 8 2013 7 12 1002
## 9 2013 7 9 1001
## 10 2013 7 17 1001
## # … with 355 more rows
В count
можно передавать логическое выражение.
## # A tibble: 3 x 2
## `dep_delay > 10` n
## <lgl> <int>
## 1 FALSE 245687
## 2 TRUE 82834
## 3 NA 8255
Функция top_n
может вывести лучший результат (или результаты) по каждой группе, основываясь на какой-то переменной. Давайте посмотрим на самую большую задержку вылета за каждый день.
## # A tibble: 370 x 4
## # Groups: year, month, day [365]
## year month day dep_delay
## <int> <int> <int> <dbl>
## 1 2013 1 1 853
## 2 2013 1 2 379
## 3 2013 1 3 291
## 4 2013 1 4 288
## 5 2013 1 5 327
## 6 2013 1 6 202
## 7 2013 1 7 366
## 8 2013 1 8 188
## 9 2013 1 9 1301
## 10 2013 1 10 1126
## # … with 360 more rows
Эти функции позволяют отобрать случайные наблюдения.
## # A tibble: 10 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 3 8 921 835 46 1408
## 2 2013 12 6 1354 1400 -6 1559
## 3 2013 7 28 1025 1029 -4 1143
## 4 2013 11 7 2058 2100 -2 2209
## 5 2013 12 30 2018 2005 13 2339
## 6 2013 1 18 636 640 -4 901
## 7 2013 12 29 1212 1151 21 1517
## 8 2013 4 5 1929 1930 -1 2250
## 9 2013 10 25 1854 1900 -6 2049
## 10 2013 3 22 558 600 -2 850
## # … with 12 more variables: sched_arr_time <int>, arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>,
## # time_hour <dttm>
## # A tibble: 3,368 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 25 NA 1705 NA NA
## 2 2013 12 29 1301 1300 1 1557
## 3 2013 3 3 724 730 -6 1012
## 4 2013 7 6 1312 1310 2 1553
## 5 2013 6 21 926 929 -3 1214
## 6 2013 9 16 1532 1539 -7 1828
## 7 2013 8 2 2113 2049 24 2358
## 8 2013 3 29 1717 1719 -2 1933
## 9 2013 7 24 1015 1015 0 1206
## 10 2013 10 29 608 610 -2 723
## # … with 3,358 more rows, and 12 more variables: sched_arr_time <int>,
## # arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>
Функция slice
позволяет отобрать наблюдения по номеру строки, в которой они находятся. Напимер, отберем с 10 по 20 наблюдения.
## # A tibble: 11 x 19
## year month day dep_time sched_dep_time dep_delay arr_time
## <int> <int> <int> <int> <int> <dbl> <int>
## 1 2013 1 1 558 600 -2 753
## 2 2013 1 1 558 600 -2 849
## 3 2013 1 1 558 600 -2 853
## 4 2013 1 1 558 600 -2 924
## 5 2013 1 1 558 600 -2 923
## 6 2013 1 1 559 600 -1 941
## 7 2013 1 1 559 559 0 702
## 8 2013 1 1 559 600 -1 854
## 9 2013 1 1 600 600 0 851
## 10 2013 1 1 600 600 0 837
## 11 2013 1 1 601 600 1 844
## # … with 12 more variables: sched_arr_time <int>, arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>,
## # time_hour <dttm>
Выдает датафрейм уникальных значений. Может принимать несколько переменных.
## # A tibble: 12 x 1
## month
## <int>
## 1 1
## 2 10
## 3 11
## 4 12
## 5 2
## 6 3
## 7 4
## 8 5
## 9 6
## 10 7
## 11 8
## 12 9
## # A tibble: 2 x 2
## `month == 1` n
## <lgl> <int>
## 1 FALSE 309772
## 2 TRUE 27004