Студенты думают, что
.csv
файлы как булки на деревьях растут!
Новички даже не предполагают, сколько времени занимает предварительная обработка данных! Удаление явно ошибочных значений, приведение к нужному формату, слияние данных из нескольких источников и прочие “мелочи”.
Загружаем нужные библиотеки:
library("knitr")
library("dplyr") # стратегия Разделяй - Властвуй - Соединяй
library("reshape2") # melt - cast
library("ggplot2") # графики
Многие преобразования могут быть описаны с помощью принципа “Разделяй и властвуй! Затем соединяй!”:
разделяем большую табличку на много маленьких;
на каждой маленькой табличке делаем простые вычисления;
соединяем результат в одну большую табличку.
Загрузим данные по стоимости квартир в Москве:
filename <- "../datasets/flats_moscow.txt"
flats <- read.table(filename, header = TRUE)
Пример. Подсчёт описательных статистик внутри групп
Мы разбиваем большую таблицу на маленькие таблички по переменным code
(географический район квартиры) и brick
(кирпичность). По каждой маленькой табличке считаем число наблюдений и среднюю цену квартиры. Затем сводим в итоговую таблицу:
flats_summ <- flats %>% group_by(code, brick) %>%
summarize(n = n(), mean = mean(price))
head(flats_summ)
## Source: local data frame [6 x 4]
## Groups: code [3]
##
## code brick n mean
## (int) (int) (int) (dbl)
## 1 1 0 180 123.0000
## 2 1 1 92 156.7391
## 3 2 0 186 105.9516
## 4 2 1 29 138.3103
## 5 3 0 169 134.7337
## 6 3 1 176 161.2216
Пример. Корректировка наблюдения на групповое среднее.
Из цены каждой квартиры будет вычтена средняя цена по квартирам данного района и данной кирпичности.
flats_new <- flats %>% group_by(code, brick) %>%
mutate(delta = price - mean(price))
head(flats_new)
## Source: local data frame [6 x 12]
## Groups: code, brick [4]
##
## n price totsp livesp kitsp dist metrdist walk brick floor code
## (int) (int) (int) (int) (dbl) (dbl) (int) (int) (int) (int) (int)
## 1 1 81 58 40 6 12.5 7 1 1 1 3
## 2 2 75 44 28 6 13.5 7 1 0 1 6
## 3 3 128 70 42 6 14.5 3 1 1 1 3
## 4 4 95 61 37 6 13.5 7 1 0 1 1
## 5 5 330 104 60 11 10.5 7 0 1 1 3
## 6 6 137 76 50 9 11.0 7 1 1 1 8
## Variables not shown: delta (dbl)
Итого:
команда mutate
в финальной табличке создаёт столько строк, сколько было в изначальной табличке;
команда summarize
в финальной табличке создаёт столько строк, на сколько мелких табличек разрезали изначальную.
для подсчета числа наблюдений бывает полезна функция n()
. Также её можно заменить на length()
и указать внутри любую переменную.
Теорема о крокодиле. Крокодил более широкий чем длинный.
Доказательство.
Шаг 1. Крокодил более широкий, чем зеленый. Зеленый он только снаружи, а широкий он и снаружи и внутри.
Шаг 2. Крокодил более зеленый, чем длинный. Зеленый он и в длину, и в ширину, а длинный - только в длину.
Шаг 3. Отношение “больше” транзитивно :)
Упражнение. Докажите, что крокодил более длинный, чем широкий.
Упражнение. Докажите, что крокодилов не существует.
Пример “широкой” таблицы:
tab_wide <- smiths
head(tab_wide)
## subject time age weight height
## 1 John Smith 1 33 90 1.87
## 2 Mary Smith 1 NA NA 1.54
Пример “длинной” таблицы:
names(airquality) <- tolower(names(airquality))
tab_long <- melt(airquality, id = c("month", "day"), na.rm = TRUE)
head(tab_long)
## month day variable value
## 1 5 1 ozone 41
## 2 5 2 ozone 36
## 3 5 3 ozone 12
## 4 5 4 ozone 18
## 6 5 6 ozone 28
## 7 5 7 ozone 23
Данные удобнее обрабатывать в “длинном” формате. В “длинном” формате при получении новых наблюдений не нужно добавлять столбцы в data.frame
. “Широкий” формат изредка бывает удобен для представления результатов. Или клиент так хочет.
Чтобы табличка растаяла из “широкого” формата и стекла вниз в “длинный” её можно растопить командой melt
из пакета reshape
:
tab_long2 <- melt(tab_wide, id = "subject")
head(tab_long2)
## subject variable value
## 1 John Smith time 1
## 2 Mary Smith time 1
## 3 John Smith age 33
## 4 Mary Smith age NA
## 5 John Smith weight 90
## 6 Mary Smith weight NA
Обратное действие выполняется командой dcast
:
tab_wide2 <- dcast(tab_long, day + month ~ variable)
head(tab_wide2)
## day month ozone solar.r wind temp
## 1 1 5 41 190 7.4 67
## 2 1 6 NA 286 8.6 78
## 3 1 7 135 269 4.1 84
## 4 1 8 39 83 6.9 81
## 5 1 9 96 167 6.9 91
## 6 2 5 36 118 8.0 72
# merge
Если операция, которую нужно выполнить очень сложная, то можно сделать её в три шага:
написать функцию, которая делает то, что нам нужно, с одним объектом;
векторизовать функцию;
применить функцию к большой табличке.
Этот подход, конечно, можно комбинировать с использованием стратегии Разделяй-Властвуй-Соединяй.