Таблицы

data.table (data.table package)

Задание 1

Создайте из векторов month.abb и month.name data.frame -- таблицу с колонками m_abb и m_name соответственно. Назовите таблицу months_df.

months_df <- data.frame(
  m_abb = month.abb,
  m_name = month.name
)

Задание 2

Пересоздайте таблицу months_df так, чтобы колонки m_abb и m_name были факторами.

Решение:

months_df <- data.frame(
  m_abb = month.abb,
  m_name = month.name,
  stringsAsFactors = TRUE
)
str(months_df)
## 'data.frame':    12 obs. of  2 variables:
##  $ m_abb : Factor w/ 12 levels "Apr","Aug","Dec",..: 5 4 8 1 9 7 6 2 12 11 ...
##  $ m_name: Factor w/ 12 levels "April","August",..: 5 4 8 1 9 7 6 2 12 11 ...

Задание 3

Установите пакет data.table. Преобразуйте объект months_df в класс data.table. Посмотрите структуру и класс объекта.

Для преобразования можно воспользоваться функцией as.data.table(), однако намного лучше использовать функцию setDT() -- эта функция осуществляет преобразование in place, без копирования объекта в памяти, что может быть полезно при больших датасетах.

# install.packages('data.table')
library(data.table)

setDT(months_df)
str(months_df)
## Classes 'data.table' and 'data.frame':   12 obs. of  2 variables:
##  $ m_abb : Factor w/ 12 levels "Apr","Aug","Dec",..: 5 4 8 1 9 7 6 2 12 11 ...
##  $ m_name: Factor w/ 12 levels "April","August",..: 5 4 8 1 9 7 6 2 12 11 ...
##  - attr(*, ".internal.selfref")=<externalptr>

Задание 4

Повторите процесс создание объекта months_df средствами пакета data.table. Созданную таблицу назовите months_dt.

months_dt <- data.table(
  m_abb = month.abb,
  m_name = month.name
)
str(months_dt)
## Classes 'data.table' and 'data.frame':   12 obs. of  2 variables:
##  $ m_abb : chr  "Jan" "Feb" "Mar" "Apr" ...
##  $ m_name: chr  "January" "February" "March" "April" ...
##  - attr(*, ".internal.selfref")=<externalptr>

Задание 5

Пересоздайте таблицу months_dt так, чтобы колонки m_abb и m_name были факторами.

months_dt <- data.table(
  m_abb = month.abb,
  m_name = month.name,
  stringsAsFactors = FALSE
)
str(months_dt)
## Classes 'data.table' and 'data.frame':   12 obs. of  2 variables:
##  $ m_abb : chr  "Jan" "Feb" "Mar" "Apr" ...
##  $ m_name: chr  "January" "February" "March" "April" ...
##  - attr(*, ".internal.selfref")=<externalptr>

Задание 6

Извлеките первую и пятую строки таблицы months_dt.

months_dt[c(1, 5)]
##    m_abb  m_name
## 1:   Jan January
## 2:   May     May

Задание 7

Извлеките первую, пятую и последнюю строки таблицы months_dt.

Последнюю строку можно вычислить с помощью функции nrow(), однако лучше воспользоваться специальной конструкцией data.table - .N, которая считает количество строк в таблице (или подтаблице, если есть группировка).

months_dt[c(1, 5, .N)]
##    m_abb   m_name
## 1:   Jan  January
## 2:   May      May
## 3:   Dec December

Задание 8

Извлеките все строки, в которых в названии месяца встречается буква M.

Возможны два решения - классическое с использованием функций grep() / grepl(). А так же решение с использованием оператора %like% пакета data.table (или одноименной функции).

# решение с grep()
months_dt[grep('M', m_name)]
##    m_abb m_name
## 1:   Mar  March
## 2:   May    May
# решение средствами data.table
months_dt[m_name %like% 'M']
##    m_abb m_name
## 1:   Mar  March
## 2:   May    May
months_dt[like(m_name, 'M')]
##    m_abb m_name
## 1:   Mar  March
## 2:   May    May

Задание 9

В строках, где в m_name встречается M, в колонке m_abb присвойте ячейкам значения NA.

months_dt[grep('M', m_name), m_abb := NA]

Задание 10

Создайте колонку ind с номерами месяцев в году и колонку nrm, в которой будет семпл из нормального распределения.

Стандартный путь - каждое создание колонки сделать отдельно. Однако можно вызвать инфиксный оператор := как функцию и произвести множественное присвоение.

# создание колонок по отдельности
months_dt[, ind := 1:.N]
months_dt[, nrm := rnorm(.N)]

# множественное присвоение
months_dt[, `:=`(ind = 1:.N, nrm = rnorm(.N))]
str(months_dt)
## Classes 'data.table' and 'data.frame':   12 obs. of  4 variables:
##  $ m_abb : chr  "Jan" "Feb" NA "Apr" ...
##  $ m_name: chr  "January" "February" "March" "April" ...
##  $ ind   : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ nrm   : num  -0.391 -0.932 0.747 -0.173 0.711 ...
##  - attr(*, ".internal.selfref")=<externalptr>

Задание 11

Создайте колонку is_winter, которая маркирует, зимний месяц или нет (значения yes / no).

Самое простое решение через ifelse() и номера месяцев.

months_dt[, is_winter := ifelse(ind %in% c(12, 1, 2), 'yes', 'no')]
str(months_dt)
## Classes 'data.table' and 'data.frame':   12 obs. of  5 variables:
##  $ m_abb    : chr  "Jan" "Feb" NA "Apr" ...
##  $ m_name   : chr  "January" "February" "March" "April" ...
##  $ ind      : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ nrm      : num  -0.391 -0.932 0.747 -0.173 0.711 ...
##  $ is_winter: chr  "yes" "yes" "no" "no" ...
##  - attr(*, ".internal.selfref")=<externalptr>

Задание 12

Сравните два выражения months_dt[, m_name] и months_dt[, list(m_name)]. Какие класс у результатов выполнения этих выражений и почему?

class(months_dt[, m_name])
## [1] "character"
class(months_dt[, list(m_name)])
## [1] "data.table" "data.frame"

Первое выражение отдает колонку как отдельный вектор, второе -- спецсинтаксис data.table, указание, что результатом выражения должна быть также data.table-таблица, с указанной в list() колонкой (или колонками).

Задание 13

Напишите выражение, которое поможет из months_dt выделить таблицу с колонками m_name и is_winter. Создавать отдельную таблицу нет необходимости.

months_dt[, list(m_name, is_winter)]
##        m_name is_winter
##  1:   January       yes
##  2:  February       yes
##  3:     March        no
##  4:     April        no
##  5:       May        no
##  6:      June        no
##  7:      July        no
##  8:    August        no
##  9: September        no
## 10:   October        no
## 11:  November        no
## 12:  December       yes

Задание 14

Повторите предыдущее задание, но в выделяемой таблице должы быть только строки с пропусками в m_abb.

months_dt[is.na(m_abb), list(m_name, is_winter)]
##    m_name is_winter
## 1:  March        no
## 2:    May        no

Задание 15

Повторите предыдущее задание, но в выделяемой таблице должы быть только строки с пропусками в m_abb и колонка ind. При выделении таблицы переименуйте ind в m_number.

months_dt[is.na(m_abb), list(m_name, is_winter, m_number = ind)]
##    m_name is_winter m_number
## 1:  March        no        3
## 2:    May        no        5

Задание 16

Подсчитайте количество строк в таблице months_dt.

months_dt[, .N]
## [1] 12

Задание 17

Подсчитайте количество не зимних месяцев в первом полугодии.

months_dt[ind > 2 & ind <= 6, .N]
## [1] 4

Задание 18

Посчитайте среднее значение по колонке nrm

months_dt[, mean(nrm)]
## [1] -0.1386398

Задание 19

Посчитайте количество месяцев и среднее значение колонки nrm для зимних и прочих месяцев.

months_dt[, list(n_months = .N, nrm_mn = mean(nrm)), by = is_winter]
##    is_winter n_months      nrm_mn
## 1:       yes        3 -0.39072653
## 2:        no        9 -0.05461088

Задание 20

Повторите предыдущее задание, только исключите месяцы, в которых в m_abb пропуски.

months_dt[!is.na(m_abb), list(n_months = .N, nrm_mn = mean(nrm)), by = is_winter]
##    is_winter n_months     nrm_mn
## 1:       yes        3 -0.3907265
## 2:        no        7 -0.2785725

Задание 21

К результату предыдущего задания добавьте еще строчку с информацией по всему датасету, без группировки (но также с фильтрацией на пропуски). В колонке is_winter для этой строки должно быть Total

rbind(
  months_dt[!is.na(m_abb), list(n_months = .N, nrm_mn = mean(nrm)), by = is_winter],
  months_dt[!is.na(m_abb), list(is_winter = 'Total', n_months = .N, nrm_mn = mean(nrm))]
)
##    is_winter n_months     nrm_mn
## 1:       yes        3 -0.3907265
## 2:        no        7 -0.2785725
## 3:     Total       10 -0.3122187

Задание 22

Отсортируйте таблицу months_dt по убыванию значений колонки nrm.

Для сортировки по убыванию можно воспользоваться функцией order(), в которой указать нужную колонку. При этом направление сортировки по убыванию можно задать как знаком - перед названием колонки, так и аргументом decreasing.

months_dt[order(-nrm)]
##     m_abb    m_name ind         nrm is_winter
##  1:   Aug    August   8  1.43328686        no
##  2:  <NA>     March   3  0.74730912        no
##  3:  <NA>       May   5  0.71120070        no
##  4:   Nov  November  11  0.60365949        no
##  5:   Dec  December  12  0.15060552       yes
##  6:   Jul      July   7 -0.03335827        no
##  7:   Apr     April   4 -0.17319232        no
##  8:   Jan   January   1 -0.39114463       yes
##  9:   Oct   October  10 -0.58800417        no
## 10:   Jun      June   6 -0.79002590        no
## 11:   Feb  February   2 -0.93164047       yes
## 12:   Sep September   9 -2.40237344        no

Задание 23

Переименуйте колонки is_winter и nrm таблицы months_dt в var1 и var2 соответственно.

setnames(months_dt, c('is_winter', 'nrm'), c('var1', 'var2'))
str(months_dt)
## Classes 'data.table' and 'data.frame':   12 obs. of  5 variables:
##  $ m_abb : chr  "Jan" "Feb" NA "Apr" ...
##  $ m_name: chr  "January" "February" "March" "April" ...
##  $ ind   : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ var2  : num  -0.391 -0.932 0.747 -0.173 0.711 ...
##  $ var1  : chr  "yes" "yes" "no" "no" ...
##  - attr(*, ".internal.selfref")=<externalptr>

Задание 24

Удалите колонку m_abb.

months_dt[, m_abb := NULL]

Задание 25

С помощью синтаксиса .SD узнайте тип колонок таблицы months_dt.

months_dt[, lapply(.SD, class)]
##       m_name     ind    var2      var1
## 1: character integer numeric character

Задание 26

Аналогично предыдущему заданию, узнайте среднее значение по численным колонкам.

months_dt[, colMeans(.SD), .SDcols = c('ind', 'var2')]
##        ind       var2 
##  6.5000000 -0.1386398

Задание 27

Склейте построчно две таблицы: dt1 <- data.table(tb = 'table_1', col1 = sample(9, 3)) и dt2 <- data.table(tb = 'table_2', col2 = sample(letters, 3)). В результате у вас должна получится таблица из 6 строк и 3 колонок.

Так как в таблицах даны разные по названиям колонки, то при склеивании необходимо использовать аргументы use.names = TRUE, fill = TRUE.

dt1 <- data.table(tb = 'table_1', col1 = sample(9, 3))
dt2 <- data.table(tb = 'table_2', col2 = sample(letters, 3))
rbind(dt1, dt2, use.names = TRUE, fill = TRUE)
##         tb col1 col2
## 1: table_1    8 <NA>
## 2: table_1    3 <NA>
## 3: table_1    4 <NA>
## 4: table_2   NA    s
## 5: table_2   NA    h
## 6: table_2   NA    o

Задание 28

Склейте по колонкам две созданные в предыдущем задании таблицы. В чем может быть проблема при такой операции?

cbind(dt1, dt2)[, .(tb)]
##         tb
## 1: table_1
## 2: table_1
## 3: table_1

Стандартная функция cbind() склеивает таблицы по колонкам, однако не проверяет уникальность названий колонок, т. е. можно получить таблицу, в которой могут быть колонки с одинаковым названием. Соответственно, любые попытки обратиться к какой-либо из этих колонок по названию вызовет только первую колонку из колонок с повторяющимся названием.

Задание 29

Склейте по ключу key_col (смерджите) две таблицы dt1 <- data.table(key_col = c('r1', 'r2', 'r3'), col_num = seq_len(3)) и dt2 <- data.table(key_col = c('r3', 'r1', 'r2'), col_char = c('c', 'a', 'b')). Сохраните все строки в обеих колонках.

dt1 <- data.table(key_col = c('r1', 'r2', 'r4'),
                  col_num = seq_len(3))

dt2 <- data.table(key_col = c('r3', 'r1', 'r2'),
                  col_char = c('c', 'a', 'b'))

# сливаем построчно по значениям в колонке key_col
merge(x = dt1, y = dt2, by = 'key_col', all = TRUE)
##    key_col col_num col_char
## 1:      r1       1        a
## 2:      r2       2        b
## 3:      r3      NA        c
## 4:      r4       3     <NA>

Задание 30

У вас есть таблица dt_long, где данные по каждому испытуемому записаны в нескольких строках, по строке на параметр. Переведите эту таблицу в стандартный широкий формат, когда на одной строке одно наблюдение, и параметры выделены в отдельные колонки. В результате должна получиться таблица из 2 строк и 2 колонок. Сохраните результат в объекте dt_wide.

dt_long <- data.table(
  id = paste0('id_', rep(1:2, each = 2)),
  variable = rep(c('age', 'height'), 2),
  value = c(25, 175, 31, 176)
)
dt_long
##      id variable value
## 1: id_1      age    25
## 2: id_1   height   175
## 3: id_2      age    31
## 4: id_2   height   176
dt_wide <- dcast(data = dt_long, formula = id ~ variable)
dt_wide
##      id age height
## 1: id_1  25    175
## 2: id_2  31    176

Задание 31

Аналогично предыдущему заданию, есть таблица dt_long, в которой на одного респондента есть несколько измерений, притом каждое измерение сделано в двух волнах обследований. Переведите эту таблицу в стандартный широкий формат, когда на одной строке одно наблюдение в одной волне, и параметры выделены в отдельные колонки. В результате должна получиться таблица из 4 строк и колонок.

dt_long <- data.table(
  wave = paste0('wave_', rep(1:2, each = 6)),
  id = paste0('id_', rep(1:4, each = 3)),
  variable = rep(c('age', 'height', 'weight'), 4),
  value = c(45, 163, 55,
            13, 142, 40,
            29, 178, 85,
            69, 155, 63))

dt_long
##       wave   id variable value
##  1: wave_1 id_1      age    45
##  2: wave_1 id_1   height   163
##  3: wave_1 id_1   weight    55
##  4: wave_1 id_2      age    13
##  5: wave_1 id_2   height   142
##  6: wave_1 id_2   weight    40
##  7: wave_2 id_3      age    29
##  8: wave_2 id_3   height   178
##  9: wave_2 id_3   weight    85
## 10: wave_2 id_4      age    69
## 11: wave_2 id_4   height   155
## 12: wave_2 id_4   weight    63

В том случае, когда данные имеют большую размерность, можно усложнить структуру широкой таблицы за счет неполного решейпа. Например, можно оставить группировку по испытуемым и по волнам, а параметры вынести в колонки.

 dcast(data = dt_long, formula = wave + id ~ variable, value.var = 'value')
##      wave   id age height weight
## 1: wave_1 id_1  45    163     55
## 2: wave_1 id_2  13    142     40
## 3: wave_2 id_3  29    178     85
## 4: wave_2 id_4  69    155     63

Задание 32

Повторите предыдущее задание, только идентификатор волны обследования вынесите в колонки так, чтобы каждый параметр потворялся по количеству волн. В результате должно получиться 4 строки и 1 + 2 * 3 (id + N волн * M параметров).

dcast(data = dt_long, formula = id ~ wave + variable, value.var = 'value')
##      id wave_1_age wave_1_height wave_1_weight wave_2_age wave_2_height
## 1: id_1         45           163            55         NA            NA
## 2: id_2         13           142            40         NA            NA
## 3: id_3         NA            NA            NA         29           178
## 4: id_4         NA            NA            NA         69           155
##    wave_2_weight
## 1:            NA
## 2:            NA
## 3:            85
## 4:            63

Задание 33

Повторите предыдущее задание, только замените NA на 0.

dcast(data = dt_long, formula = id ~ wave + variable, value.var = 'value', fill = 0)
##      id wave_1_age wave_1_height wave_1_weight wave_2_age wave_2_height
## 1: id_1         45           163            55          0             0
## 2: id_2         13           142            40          0             0
## 3: id_3          0             0             0         29           178
## 4: id_4          0             0             0         69           155
##    wave_2_weight
## 1:             0
## 2:             0
## 3:            85
## 4:            63

Задание 34

Посчитайте среднее значение по испытуемым по каждому параметру для каждой волны.

dcast(data = dt_long, formula = wave ~ variable, value.var = 'value', fun.aggregate = mean)
##      wave age height weight
## 1: wave_1  29  152.5   47.5
## 2: wave_2  49  166.5   74.0

Задание 35

Проведите операцию, обратную Заданию 29 - из широкой таблицы dt_wide сделайте таблицу в длинном формате.

melt(data = dt_wide,
     id.vars = 'id',
     measure.vars = c('age', 'height'),
     variable.name = 'variable',
     value.name = 'value')
##      id variable value
## 1: id_1      age    25
## 2: id_2      age    31
## 3: id_1   height   175
## 4: id_2   height   176

tibble (tidyr package)

Задание 1

Создайте из векторов month.abb и month.name data.frame - таблицу c колонками m_abb и m_name соответственно. Назовите таблицу months_df.

months_df <- data.frame(
  m_abb = month.abb,
  m_name = month.name
)

Задание 2

Пересоздайте таблицу months_df так, чтобы колонки m_abb и m_name были факторами.

months_df <- data.frame(
  m_abb = month.abb,
  m_name = month.name,
  stringsAsFactors = TRUE
)
str(months_df)
## 'data.frame':    12 obs. of  2 variables:
##  $ m_abb : Factor w/ 12 levels "Apr","Aug","Dec",..: 5 4 8 1 9 7 6 2 12 11 ...
##  $ m_name: Factor w/ 12 levels "April","August",..: 5 4 8 1 9 7 6 2 12 11 ...

Задание 3

Установите пакеты dplyr и tidyr. Преобразуйте объект months_df в тип tibble. Посмотрите структуру и класс объекта.

# install.packages('tidyr')
library(tidyr)
library(dplyr)

months_tb <- as_tibble(months_df)
str(months_tb)
## tibble [12 × 2] (S3: tbl_df/tbl/data.frame)
##  $ m_abb : Factor w/ 12 levels "Apr","Aug","Dec",..: 5 4 8 1 9 7 6 2 12 11 ...
##  $ m_name: Factor w/ 12 levels "April","August",..: 5 4 8 1 9 7 6 2 12 11 ...

Задание 4

Повторите процесс создание объекта months_df средствами пакета dplyr. Созданную таблицу назовите months_tb.

months_tb <- tibble(
  m_abb = month.abb,
  m_name = month.name
)
str(months_tb)
## tibble [12 × 2] (S3: tbl_df/tbl/data.frame)
##  $ m_abb : chr [1:12] "Jan" "Feb" "Mar" "Apr" ...
##  $ m_name: chr [1:12] "January" "February" "March" "April" ...

Задание 5

Извлеките первую и пятую строки таблицы months_tb.

months_tb %>%
  slice(c(1, 5))
## # A tibble: 2 × 2
##   m_abb m_name 
##   <chr> <chr>  
## 1 Jan   January
## 2 May   May

Задание 6

Извлеките первую, пятую и последнюю строки таблицы months_tb.

Для вычисления номера последней строки можно воспрользоваться как базовой функцией nrow(), так и функцией n() пакета dplyr.

months_tb %>%
  slice(c(1, 5, n()))
## # A tibble: 3 × 2
##   m_abb m_name  
##   <chr> <chr>   
## 1 Jan   January 
## 2 May   May     
## 3 Dec   December

Задание 7

Извлеките все строки, в которых в названии месяца встречается буква M.

months_tb %>%
  filter(grepl('M', m_name))
## # A tibble: 2 × 2
##   m_abb m_name
##   <chr> <chr> 
## 1 Mar   March 
## 2 May   May

Задание 8

В строках, где в m_name встречается M, в колонке m_abb присвойте ячейкам значения NA.

months_tb <- months_tb %>%
  mutate(m_abb = replace(m_abb, grepl('M', m_name), NA))

Задание 9

Создайте колонку ind с номерами месяцев в году и колонку nrm, в которой будет семпл из нормального распределения.

months_tb <- months_tb %>%
  mutate(ind = 1:nrow(months_tb),
         nrm = rnorm(n()))
str(months_tb)
## tibble [12 × 4] (S3: tbl_df/tbl/data.frame)
##  $ m_abb : chr [1:12] "Jan" "Feb" NA "Apr" ...
##  $ m_name: chr [1:12] "January" "February" "March" "April" ...
##  $ ind   : int [1:12] 1 2 3 4 5 6 7 8 9 10 ...
##  $ nrm   : num [1:12] 0.382 -1.636 0.35 -1.359 -1.009 ...

Задание 10

Создайте колонку is_winter, которая маркирует, зимний месяц или нет (значения yes / no).

Самое простое решение через ifelse() и номера месяцев.

months_tb <- months_tb %>%
  mutate(is_winter = ifelse(ind %in% c(12, 1, 2), 'yes', 'no'))
str(months_tb)
## tibble [12 × 5] (S3: tbl_df/tbl/data.frame)
##  $ m_abb    : chr [1:12] "Jan" "Feb" NA "Apr" ...
##  $ m_name   : chr [1:12] "January" "February" "March" "April" ...
##  $ ind      : int [1:12] 1 2 3 4 5 6 7 8 9 10 ...
##  $ nrm      : num [1:12] 0.382 -1.636 0.35 -1.359 -1.009 ...
##  $ is_winter: chr [1:12] "yes" "yes" "no" "no" ...

Задание 11

Напишите выражение, которое поможет из months_tb выделить таблицу с колонками m_name и is_winter. Создавать отдельную таблицу нет необходимости.

months_tb %>%
  select(m_name, is_winter)
## # A tibble: 12 × 2
##    m_name    is_winter
##    <chr>     <chr>    
##  1 January   yes      
##  2 February  yes      
##  3 March     no       
##  4 April     no       
##  5 May       no       
##  6 June      no       
##  7 July      no       
##  8 August    no       
##  9 September no       
## 10 October   no       
## 11 November  no       
## 12 December  yes

Задание 12

Повторите предыдущее задание, но в выделяемой таблице должы быть только строки с пропусками в m_abb.

months_tb %>%
  filter(is.na(m_abb)) %>%
  select(m_name, is_winter)
## # A tibble: 2 × 2
##   m_name is_winter
##   <chr>  <chr>    
## 1 March  no       
## 2 May    no

Задание 13

Повторите предыдущее задание, но в выделяемой таблице должы быть только строки с пропусками в m_abb и колонка ind. При выделении таблицы переименуйте ind в m_number.

months_tb %>%
  filter(!is.na(m_abb)) %>%
  select(m_name, is_winter, m_number = ind)
## # A tibble: 10 × 3
##    m_name    is_winter m_number
##    <chr>     <chr>        <int>
##  1 January   yes              1
##  2 February  yes              2
##  3 April     no               4
##  4 June      no               6
##  5 July      no               7
##  6 August    no               8
##  7 September no               9
##  8 October   no              10
##  9 November  no              11
## 10 December  yes             12

Задание 14

Подсчитайте количество строк в таблице months_tb.

nrow(months_tb)
## [1] 12

Задание 15

Подсчитайте количество не зимних месяцев в первом полугодии.

months_tb %>%
  filter(ind > 2 & ind <= 6) %>%
  nrow()
## [1] 4

Задание 16

Посчитайте среднее значение по колонке nrm

months_tb %>%
  summarise(mean(nrm))
## # A tibble: 1 × 1
##   `mean(nrm)`
##         <dbl>
## 1      -0.358

Задание 17

Посчитайте количество месяцев и среднее значение колонки nrm для зимних и прочих месяцев.

months_tb %>%
  group_by(is_winter) %>%
  summarise(n_months = length(nrm), nrm = mean(nrm))
## # A tibble: 2 × 3
##   is_winter n_months    nrm
##   <chr>        <int>  <dbl>
## 1 no               9 -0.317
## 2 yes              3 -0.480

Задание 18

Повторите предыдущее задание, только исключите месяцы, в которых в m_abb пропуски.

months_tb %>%
  filter(!is.na(m_abb)) %>%
  group_by(is_winter) %>%
  summarise(n_months = length(nrm), nrm = mean(nrm))
## # A tibble: 2 × 3
##   is_winter n_months    nrm
##   <chr>        <int>  <dbl>
## 1 no               7 -0.314
## 2 yes              3 -0.480

Задание 19

К результату предыдущего задания добавьте еще строчку с информацией по всему датасету, без группировки (но также с фильтрацией на пропуски). В колонке is_winter для этой строки должно быть Total

rbind(
  months_tb %>%
    filter(!is.na(m_abb)) %>%
    group_by(is_winter) %>%
    summarise(n_months = length(nrm), nrm = mean(nrm)),

  months_tb %>%
    filter(!is.na(m_abb)) %>%
    summarise(is_winter = 'Total', n_months = length(nrm), nrm = mean(nrm))
)
## # A tibble: 3 × 3
##   is_winter n_months    nrm
##   <chr>        <int>  <dbl>
## 1 no               7 -0.314
## 2 yes              3 -0.480
## 3 Total           10 -0.364

Задание 20

Отсортируйте таблицу months_tb по убыванию значений колонки nrm.

Для сортировки по убыванию можно воспользоваться функцией arrange(), в которой указать нужную колонку. При этом направление сортировки по убыванию можно задать знаком -.

months_tb %>%
  arrange(-nrm)
## # A tibble: 12 × 5
##    m_abb m_name      ind     nrm is_winter
##    <chr> <chr>     <int>   <dbl> <chr>    
##  1 Sep   September     9  2.15   no       
##  2 Aug   August        8  0.407  no       
##  3 Jan   January       1  0.382  yes      
##  4 <NA>  March         3  0.350  no       
##  5 Jul   July          7 -0.0418 no       
##  6 Nov   November     11 -0.130  no       
##  7 Dec   December     12 -0.187  yes      
##  8 Oct   October      10 -0.758  no       
##  9 <NA>  May           5 -1.01   no       
## 10 Apr   April         4 -1.36   no       
## 11 Feb   February      2 -1.64   yes      
## 12 Jun   June          6 -2.47   no

Задание 21

Переименуйте колонки is_winter и nrm таблицы months_tb в var1 и var2 соответственно.

months_tb <- months_tb %>%
  rename(var1 = is_winter, var2 = nrm)
str(months_tb)
## tibble [12 × 5] (S3: tbl_df/tbl/data.frame)
##  $ m_abb : chr [1:12] "Jan" "Feb" NA "Apr" ...
##  $ m_name: chr [1:12] "January" "February" "March" "April" ...
##  $ ind   : int [1:12] 1 2 3 4 5 6 7 8 9 10 ...
##  $ var2  : num [1:12] 0.382 -1.636 0.35 -1.359 -1.009 ...
##  $ var1  : chr [1:12] "yes" "yes" "no" "no" ...

Задание 22

Удалите колонку m_abb.

months_tb <- months_tb %>%
  select(-m_abb)
str(months_tb)
## tibble [12 × 4] (S3: tbl_df/tbl/data.frame)
##  $ m_name: chr [1:12] "January" "February" "March" "April" ...
##  $ ind   : int [1:12] 1 2 3 4 5 6 7 8 9 10 ...
##  $ var2  : num [1:12] 0.382 -1.636 0.35 -1.359 -1.009 ...
##  $ var1  : chr [1:12] "yes" "yes" "no" "no" ...

Задание 23

Узнайте среднее значение по численным колонкам.

months_tb %>%
  summarise(mean(ind), mean(var2))
## # A tibble: 1 × 2
##   `mean(ind)` `mean(var2)`
##         <dbl>        <dbl>
## 1         6.5       -0.358

Задание 24

Склейте построчно две таблицы: tbl1 <- tibble(tb = 'table_1', col1 = sample(9, 3)) и tbl2 <- tibble(tb = 'table_2', col2 = sample(letters, 3)). В результате у вас должна получится таблица из 6 строк и 3 колонок.

tbl1 <- tibble(tb = 'table_1', col1 = sample(9, 3))
tbl2 <- tibble(tb = 'table_2', col2 = sample(letters, 3))
bind_rows(tbl1, tbl2)
## # A tibble: 6 × 3
##   tb       col1 col2 
##   <chr>   <int> <chr>
## 1 table_1     1 <NA> 
## 2 table_1     7 <NA> 
## 3 table_1     9 <NA> 
## 4 table_2    NA b    
## 5 table_2    NA u    
## 6 table_2    NA w

Задание 25

Склейте по колонкам две созданные в предыдущем задании таблицы.

Так как в таблицах встречаются колонки с одинаковым названием (tb), то при склеивании происходит дедупликация названий - второе и следующие повторяющиеся названия получают индекс 1, 2 и т. д.

bind_cols(tbl1, tbl2)
## # A tibble: 3 × 4
##   tb...1   col1 tb...3  col2 
##   <chr>   <int> <chr>   <chr>
## 1 table_1     1 table_2 b    
## 2 table_1     7 table_2 u    
## 3 table_1     9 table_2 w

Задание 26

Склейте по ключу key_col (смерджите) две таблицы tbl1 <- tibble(key_col = c('r1', 'r2', 'r3'), col_num = seq_len(3)) и tbl2 <- tibble(key_col = c('r3', 'r1', 'r2'), col_char = c('c', 'a', 'b')). Сохраните все строки в обеих колонках.

tbl1 <- tibble(key_col = c('r1', 'r2', 'r4'),
               col_num = seq_len(3))

tbl2 <- tibble(key_col = c('r3', 'r1', 'r2'),
               col_char = c('c', 'a', 'b'))

# сливаем построчно по значениям в колонке key_col
full_join(x = tbl1, y = tbl2, by = 'key_col')
## # A tibble: 4 × 3
##   key_col col_num col_char
##   <chr>     <int> <chr>   
## 1 r1            1 a       
## 2 r2            2 b       
## 3 r4            3 <NA>    
## 4 r3           NA c

Задание 27

У вас есть таблица tbl_long, где данные по каждому испытуемому записаны в нескольких строках, по строке на параметр. Переведите эту таблицу в стандартный широкий формат, когда на одной строке одно наблюдение, и параметры выделены в отдельные колонки. В результате должна получиться таблица из 2 строк и 2 колонок. Сохраните результат в объекте tbl_wide.

tbl_long <- tibble(
  id = paste0('id_', rep(1:2, each = 2)),
  variable = rep(c('age', 'height'), 2),
  value = c(25, 175, 31, 176)
)
tbl_long
## # A tibble: 4 × 3
##   id    variable value
##   <chr> <chr>    <dbl>
## 1 id_1  age         25
## 2 id_1  height     175
## 3 id_2  age         31
## 4 id_2  height     176
tbl_wide <- tbl_long %>%
    pivot_wider(id_cols = id, names_from = variable, values_from = value)
tbl_wide
## # A tibble: 2 × 3
##   id      age height
##   <chr> <dbl>  <dbl>
## 1 id_1     25    175
## 2 id_2     31    176

Задание 28

Аналогично предыдущему заданию, есть таблица tbl_long, в которой на одного респондента есть несколько измерений, притом каждое измерение сделано в двух волнах обследований. Переведите эту таблицу в стандартный широкий формат, когда на одной строке одно наблюдение в одной волне, и параметры выделены в отдельные колонки. В результате должна получиться таблица из 4 строк и колонок.

tbl_long <- tibble(
  wave = paste0('wave_', rep(1:2, each = 6)),
  id = paste0('id_', rep(1:4, each = 3)),
  variable = rep(c('age', 'height', 'weight'), 4),
  value = c(45, 163, 55,
            13, 142, 40,
            29, 178, 85,
            69, 155, 63))

tbl_long
## # A tibble: 12 × 4
##    wave   id    variable value
##    <chr>  <chr> <chr>    <dbl>
##  1 wave_1 id_1  age         45
##  2 wave_1 id_1  height     163
##  3 wave_1 id_1  weight      55
##  4 wave_1 id_2  age         13
##  5 wave_1 id_2  height     142
##  6 wave_1 id_2  weight      40
##  7 wave_2 id_3  age         29
##  8 wave_2 id_3  height     178
##  9 wave_2 id_3  weight      85
## 10 wave_2 id_4  age         69
## 11 wave_2 id_4  height     155
## 12 wave_2 id_4  weight      63

В том случае, когда данные имеют большую размерность, можно усложнить структуру широкой таблицы за счет неполного решейпа. Например, можно оставить группировку по испытуемым и по волнам, а параметры вынести в колонки.

tbl_long %>%
  pivot_wider(id_cols = c(wave, id), names_from = variable, values_from = value)
## # A tibble: 4 × 5
##   wave   id      age height weight
##   <chr>  <chr> <dbl>  <dbl>  <dbl>
## 1 wave_1 id_1     45    163     55
## 2 wave_1 id_2     13    142     40
## 3 wave_2 id_3     29    178     85
## 4 wave_2 id_4     69    155     63

Задание 29

Повторите предыдущее задание, только идентификатор волны обследования вынесите в колонки так, чтобы каждый параметр потворялся по количеству волн. В результате должно получиться 4 строки и 1 + 2 * 3 (id + N волн * M параметров).

tbl_long %>%
    pivot_wider(id_cols = id,
              names_from = c(wave, variable),
              values_from = value)
## # A tibble: 4 × 7
##   id    wave_1_age wave_1_height wave_1_weight wave_2_age wave_2_height
##   <chr>      <dbl>         <dbl>         <dbl>      <dbl>         <dbl>
## 1 id_1          45           163            55         NA            NA
## 2 id_2          13           142            40         NA            NA
## 3 id_3          NA            NA            NA         29           178
## 4 id_4          NA            NA            NA         69           155
## # … with 1 more variable: wave_2_weight <dbl>

Задание 30

Повторите предыдущее задание, только замените NA на 0.

tbl_long %>%
  pivot_wider(id_cols = id,
              names_from = c(wave, variable),
              values_from = value,
              values_fill = list(value = 0))
## # A tibble: 4 × 7
##   id    wave_1_age wave_1_height wave_1_weight wave_2_age wave_2_height
##   <chr>      <dbl>         <dbl>         <dbl>      <dbl>         <dbl>
## 1 id_1          45           163            55          0             0
## 2 id_2          13           142            40          0             0
## 3 id_3           0             0             0         29           178
## 4 id_4           0             0             0         69           155
## # … with 1 more variable: wave_2_weight <dbl>

Задание 31

Посчитайте среднее значение по испытуемым по каждому параметру для каждой волны.

tbl_long %>%
  pivot_wider(id_cols = wave,
              names_from = variable,
              values_from = value,
              values_fn = list(value = mean))
## # A tibble: 2 × 4
##   wave     age height weight
##   <chr>  <dbl>  <dbl>  <dbl>
## 1 wave_1    29   152.   47.5
## 2 wave_2    49   166.   74

Задание 32

Проведите операцию, обратную Заданию 29 - из широкой таблицы tbl_wide сделайте таблицу в длинном формате.

tbl_wide %>%
  pivot_longer(
    cols = c(age, height),
    names_to = 'variable',
    values_to = 'value')
## # A tibble: 4 × 3
##   id    variable value
##   <chr> <chr>    <dbl>
## 1 id_1  age         25
## 2 id_1  height     175
## 3 id_2  age         31
## 4 id_2  height     176