Преобразования данных

Новички даже не предполагают, сколько времени занимает предварительная обработка данных! Удаление явно ошибочных значений, приведение к нужному формату, слияние данных из нескольких источников и прочие “мелочи”.

Загружаем нужные библиотеки:

library(knitr)
opts_chunk$set(cache = TRUE)  # кэшируем куски Rmd файла для скоростной компиляции после

library(plyr)  # ddply
library(reshape)  # melt - cast
library(ggplot2)  # графики

Создание выборок (нужно ли?)

Разделяй и властвуй! Затем соединяй!

Многие преобразования могут быть описаны с помощью принципа “Разделяй и властвуй! Затем соединяй!”:

Загрузим данные по стоимости квартир в Москве:

file <- "~/science/econometrix/em301/datasets/flats_moscow.txt"
h <- read.table(file, header = TRUE)

Пример. Подсчёт описательных статистик внутри групп

Мы разбиваем большую таблицу на маленькие таблички по переменным code (географический район квартиры) и brick (кирпичность). По каждой маленькой табличке считаем число наблюдений и среднюю цену квартиры. Затем сводим в итоговую таблицу:

h.summ <- ddply(h, ~code + brick, summarize, n = length(price), mean = mean(price))
head(h.summ)
##   code brick   n  mean
## 1    1     0 180 123.0
## 2    1     1  92 156.7
## 3    2     0 186 106.0
## 4    2     1  29 138.3
## 5    3     0 169 134.7
## 6    3     1 176 161.2

Пример. Корректировка наблюдения на групповое среднее. Из цены каждой квартиры будет вычтена средняя цена по квартирам данного района и данной кирпичности.

h.new <- ddply(h, ~code + brick, transform, delta = price - mean(price))
head(h.new)
##    n price totsp livesp kitsp dist metrdist walk brick floor code delta
## 1  4    95    61     37     6 13.5        7    1     0     1    1   -28
## 2 24    95    58     38     6 12.0        8    1     0     1    1   -28
## 3 38   120    77     47    12 13.5       10    1     0     1    1    -3
## 4 47   129    79     46    13 12.0       15    1     0     1    1     6
## 5 67   135    77     47    10 13.5       10    0     0     1    1    12
## 6 68   100    78     44     8 13.5       20    0     0     1    1   -23

Итого:

Из опыта. Для подсчета числа наблюдений бывает полезна функция nrow(). Функция nrow() работает только без имени переменной и без summarize.

Длинная и широкая

Теорема. Крокодил более широкий чем длинный.

Доказательство.

Шаг 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
## 5     5   6    ozone    28
## 6     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

Обратное действие выполняется командой cast.

tab.wide2 <- cast(tab.long, day + month ~ variable, mean)
head(tab.wide2)
##   day month ozone solar.r wind temp
## 1   1     5    41     190  7.4   67
## 2   1     6   NaN     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

Векторизация функций

Если операция, которую нужно выполнить очень сложная, то можно сделать её в три шага:

Этот подход, конечно, можно комбинировать с использованием функции ddply.