library(tidyverse)
# Раскомментируйте и запустите следующие команды,
# если у вас не ставится tidyverse
#library(dplyr)
#library(tidyr)
#library(ggplot2)
Данные могут быть представлены в различной форме. Следующие таблицы содержат одни и те же данные - динамику количества случаев заболевания (cases) и численности населения (population) в разных странах (country). Хотя данные одни и те же, структура таблиц различается:
table1
## # A tibble: 6 x 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 37737 172006362
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
table2
## # A tibble: 12 x 4
## country year type count
## <chr> <int> <chr> <int>
## 1 Afghanistan 1999 cases 745
## 2 Afghanistan 1999 population 19987071
## 3 Afghanistan 2000 cases 2666
## 4 Afghanistan 2000 population 20595360
## 5 Brazil 1999 cases 37737
## 6 Brazil 1999 population 172006362
## 7 Brazil 2000 cases 80488
## 8 Brazil 2000 population 174504898
## 9 China 1999 cases 212258
## 10 China 1999 population 1272915272
## 11 China 2000 cases 213766
## 12 China 2000 population 1280428583
table3
## # A tibble: 6 x 3
## country year rate
## * <chr> <int> <chr>
## 1 Afghanistan 1999 745/19987071
## 2 Afghanistan 2000 2666/20595360
## 3 Brazil 1999 37737/172006362
## 4 Brazil 2000 80488/174504898
## 5 China 1999 212258/1272915272
## 6 China 2000 213766/1280428583
table4a # cases
## # A tibble: 3 x 3
## country `1999` `2000`
## * <chr> <int> <int>
## 1 Afghanistan 745 2666
## 2 Brazil 37737 80488
## 3 China 212258 213766
table4b # population
## # A tibble: 3 x 3
## country `1999` `2000`
## * <chr> <int> <int>
## 1 Afghanistan 19987071 20595360
## 2 Brazil 172006362 174504898
## 3 China 1272915272 1280428583
table5
## # A tibble: 6 x 4
## country century year rate
## * <chr> <chr> <chr> <chr>
## 1 Afghanistan 19 99 745/19987071
## 2 Afghanistan 20 00 2666/20595360
## 3 Brazil 19 99 37737/172006362
## 4 Brazil 20 00 80488/174504898
## 5 China 19 99 212258/1272915272
## 6 China 20 00 213766/1280428583
Вопрос: В каком из представлений легче всего рассчитать в R относительную частоту заболевания - число случаев на 10000 жителей?
Наиболее удобно представление данных, в котором:
Данные в такой форме будем называть хорошо упорядоченными (tidy).
“Хорошо упорядоченные” данные
Преимуществом такой формы представления данных является единообразие: любая операция выполняется со столбцами таблицы, не требуется дополнительных действий, чтобы обратиться к нужным данным. Большинство функций в R ориентированы на векторную обработку значений, то есть они работают именно со столбцами значений.
Вопрос: где находятся переменные в рассмотренных примерах таблиц?
В противоположность “хорошо упорядоченным” данным, все остальные представления данных можно назвать “плохо упорядоченными” (messy). Этот термин означает лишь то, что обработка таких данных функциями для работы с таблицами будет более трудной. Это не значит, что сами данные - плохие или непригодные к анализу. Бывают ситуации, когда “плохая” для компьютерной обработки структура данных оказывается более удобной для человека - например, нам удобнее следить за динамикой показателей в сводных таблицах, где разные периоды времени отражаются отдельными столбцами.
Иногда данные приходится специально делать “плохо упорядоченными”, объединяя несколько переменных в одном столбце, чтобы обеспечить их автоматизированную обработку.
Например, если требуется визуализировать динамику населения и количества случаев заболеваний, то для “плохо упорядоченного” набора данных это можно сделать одной командой, а для “хорошо упорядоченного” потребуется несколько.
table2
## # A tibble: 12 x 4
## country year type count
## <chr> <int> <chr> <int>
## 1 Afghanistan 1999 cases 745
## 2 Afghanistan 1999 population 19987071
## 3 Afghanistan 2000 cases 2666
## 4 Afghanistan 2000 population 20595360
## 5 Brazil 1999 cases 37737
## 6 Brazil 1999 population 172006362
## 7 Brazil 2000 cases 80488
## 8 Brazil 2000 population 174504898
## 9 China 1999 cases 212258
## 10 China 1999 population 1272915272
## 11 China 2000 cases 213766
## 12 China 2000 population 1280428583
ggplot(data = table2) +
geom_line(mapping = aes(color = country,
x = year,
y = count)) +
facet_wrap(~ type, scales = 'free_y') +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = 1999:2000)
table1
## # A tibble: 6 x 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 37737 172006362
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
# Динамика случаев заболевания
p1 <- ggplot(data = table1) +
geom_line(mapping = aes(color = country,
x = year,
y = cases)) +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = 1999:2000) +
scale_color_discrete(guide = FALSE)
# Динамика населения
p2 <- ggplot(data = table1) +
geom_line(mapping = aes(color = country,
x = year,
y = population)) +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = 1999:2000)
# Собираем два графика на одну визуализацию
gridExtra::grid.arrange(p1, p2, ncol = 2)
В этом блокноте мы рассмотрим функции пакета tidyr, позволяющие привести данные к “хорошо упорядоченному” формату:
gather() - свертка столбцов в строки;spread() - развертка строк в столбцы;separate() - разделение значений одного столбца на несколько;unite() - объединение значений нескольких столбцов в один.Более подробно познакомиться с проблемой реструктурирования данных в следующих источниках:
tidyr (выполните команду: vignette('tidy-data')).gather()Одной из проблем набора данных может быть то, что в названиях столбцов содержатся не названия переменных, а значения переменных. Чтобы привести данные к удобному формату, нужно собрать (gather) данные столбцов в две новые переменные.
Работа функции gather()
Функция gather() имеет следующие параметры:
data - набор данных;key - название новой переменной, в которой будут храниться названия старых столбцов;value - название новой переменной, в которой будут храниться значения ячеек старых столбцов.gather()В наборе данных table4a названия столбцов 1999 и 2000 являются значениями переменной year. С помощью функции gather() данные столбцов будут свернуты в две переменные: year с названиями столбцов 1999 и 2000 и cases с значениями ячеек столбцов 1999 и 2000.
table4a
## # A tibble: 3 x 3
## country `1999` `2000`
## * <chr> <int> <int>
## 1 Afghanistan 745 2666
## 2 Brazil 37737 80488
## 3 China 212258 213766
gather(table4a, `1999`,`2000`, key = "year", value = "cases")
## # A tibble: 6 x 3
## country year cases
## <chr> <chr> <int>
## 1 Afghanistan 1999 745
## 2 Brazil 1999 37737
## 3 China 1999 212258
## 4 Afghanistan 2000 2666
## 5 Brazil 2000 80488
## 6 China 2000 213766
gather()Произведите свертку столбцов следующего набора данных:
sales <- tibble(
goods = c("Milk", "Cheese", "Butter", "Sour cream"),
moscow = c(350,430,360,570),
`st-petersburg` = c(210,270,150,250),
novosibirsk = c(120,150,210,140),
total = c(680,850,720,960)
)
sales
## # A tibble: 4 x 5
## goods moscow `st-petersburg` novosibirsk total
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Milk 350 210 120 680
## 2 Cheese 430 270 150 850
## 3 Butter 360 150 210 720
## 4 Sour cream 570 250 140 960
# Напишите свой код здесь
spread()Иногда наблюдения “разбросаны” по нескольким строкам. В этом случае функция spread() позволяет собрать данные, относящиеся к одному наблюдению в одну строку.
Работа функции spread()
Функция spread() имеет следующие параметры:
data - набор данных;key - название столбца, в котором содержатся названия переменных, для которых будут созданы столбцы;value - название столбца, в котором содержатся значения переменных.spread()В наборе данных table2 столбце type содержатся названия переменных cases и population, а в столбце count - значения переменных. С помощью функции spread() создадим переменные cases и population и перенесем в них значения из столбца count:
table2
## # A tibble: 12 x 4
## country year type count
## <chr> <int> <chr> <int>
## 1 Afghanistan 1999 cases 745
## 2 Afghanistan 1999 population 19987071
## 3 Afghanistan 2000 cases 2666
## 4 Afghanistan 2000 population 20595360
## 5 Brazil 1999 cases 37737
## 6 Brazil 1999 population 172006362
## 7 Brazil 2000 cases 80488
## 8 Brazil 2000 population 174504898
## 9 China 1999 cases 212258
## 10 China 1999 population 1272915272
## 11 China 2000 cases 213766
## 12 China 2000 population 1280428583
spread(table2, key = type, value = count)
## # A tibble: 6 x 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 37737 172006362
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
spread()Произведите развертку строк следующего набора данных:
grades <- tribble(
~name, ~subject, ~grade,
#-----------------|--------|------
"Ivan Ivanov", "Logistics", 4,
"Ivan Ivanov", "Research seminar", 5,
"Ivan Ivanov", "Logistics", 10,
"Peter Petrov", "Logistics", 8,
"Peter Petrov", "Research seminar", 8
)
grades
## # A tibble: 5 x 3
## name subject grade
## <chr> <chr> <dbl>
## 1 Ivan Ivanov Logistics 4
## 2 Ivan Ivanov Research seminar 5
## 3 Ivan Ivanov Logistics 10
## 4 Peter Petrov Logistics 8
## 5 Peter Petrov Research seminar 8
# Напишите свой код здесь
separate()Иногда значения нескольких переменных могут быть записаны в одном столбце через разделитель. В этом случае для обработки значений этих переменных необходимо разнести их по столбцам. Справиться с этой проблемой позволяет функция separate().
Работа функции separate()
Функция separate() имеет следующие параметры:
data - набор данных;col - название столбца, содержащего значения, которые нужно разделить;into - вектор названий столбцов, в которые будут помещены разделенные значения;sep - разделитель значений, по умолчанию - любой встречающийся символ, не являющийся буквой или цифрой;convert - если параметр равен TRUE, то разделенные значения будут конвертированы в наиболее подходящие типы. Параметр особенно полезен, когда разделяемые значения - числовые.separate()В наборе данных table3 в столбце rate записаны через разделитель “/” значения переменных cases и population. Разнесем их в соответствующие столбцы.
table3
## # A tibble: 6 x 3
## country year rate
## * <chr> <int> <chr>
## 1 Afghanistan 1999 745/19987071
## 2 Afghanistan 2000 2666/20595360
## 3 Brazil 1999 37737/172006362
## 4 Brazil 2000 80488/174504898
## 5 China 1999 212258/1272915272
## 6 China 2000 213766/1280428583
separate(table3, rate, into = c("cases", "population"))
## # A tibble: 6 x 4
## country year cases population
## <chr> <int> <chr> <chr>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 37737 172006362
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
separate(table3, rate, into = c("cases", "population"), convert = TRUE)
## # A tibble: 6 x 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 37737 172006362
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
separate()Разделите значения в следующего набора данных:
addresses <- tibble(address = c(
"123022, г. Москва, Б. Трехсвятительский пер., д.3",
"105187, г. Москва, ул. Кирпичная, д.33",
"100100, г. Москва, ул. Мясницкая, д.13, стр. 4"
)
)
# Напишите свой код здесь
unite()Функция unite() позволяет соединить значения нескольких столбцов в один.
Работа функции unite()
Функция имеет следующие параметры:
data - набор данных;col - название нового столбца, в котором будут соединенные значения;sep - разделитель значений в новом столбце, по умолчанию "_".unite()В наборе данных table5 первые и последние две цифры года разнесены по столбцам century и year. Соединим их в столбце new.
table5
## # A tibble: 6 x 4
## country century year rate
## * <chr> <chr> <chr> <chr>
## 1 Afghanistan 19 99 745/19987071
## 2 Afghanistan 20 00 2666/20595360
## 3 Brazil 19 99 37737/172006362
## 4 Brazil 20 00 80488/174504898
## 5 China 19 99 212258/1272915272
## 6 China 20 00 213766/1280428583
unite(table5, new, century, year, sep = "")
## # A tibble: 6 x 3
## country new rate
## <chr> <chr> <chr>
## 1 Afghanistan 1999 745/19987071
## 2 Afghanistan 2000 2666/20595360
## 3 Brazil 1999 37737/172006362
## 4 Brazil 2000 80488/174504898
## 5 China 1999 212258/1272915272
## 6 China 2000 213766/1280428583
unite()Используя функцию unite(), создайте столбец, в котором для каждой даты проставлено соответствие времени года и год. Например, для даты “01-01-2017” - “зима 2017”.
dates <- tibble(date = c("02-01-2015", "05-04-2015", "27-09-2017", "18-07-2016","09-12-2014"))
# Напишите свой код здесь