На этой лекции мы будем работать с базой данных, содержащей результаты выборов президента в 2012 году.
Для начала приведем эту базу данных к более удобному виду – проделаем те же действия, что и на прошлом семинаре. Загрузим базу данных (учтем кодировку!), выберем нужные переменные (столбцы) и присвоим им более содержательные названия.
library(dplyr)
el <- read.csv("47130-8314.csv", encoding = "UTF-8")
el <- el %>% select(kom1, kom2, kom3, X1, X9, X10, X19, X20, X21, X22, X23)
colnames(el) <- c("region", "tik", "uik", "total", "invalid", "valid",
"Zh", "Zug", "Mir", "Pro", "Put")
Добавим переменную turnout (явка, число голосов) и turnout_perc (явка, в процентах). Удалим строки с пропущенными значениями и территорию за пределами РФ.
el <- el %>% mutate(turnout = invalid + valid)
el <- el %>% mutate(turnout_perc = turnout / total * 100)
el <- el %>% filter(region != "Территория за пределами РФ", region != "Город Байконур (Республика Казахстан)")
el <- na.omit(el)
Агрегируем результаты по регионам (суммируем) и добавим показатели в процентах:
aggr_reg <- el %>% group_by(region) %>%
summarise(total = sum(total),
turnout = sum(turnout),
Zh = sum(Zh),
Zug = sum(Zug),
Mir = sum(Mir),
Pro = sum(Pro),
Put = sum(Put))
aggr_reg <- aggr_reg %>% mutate(turnout_perc = turnout / total * 100,
Zh_perc = Zh / turnout * 100,
Zug_perc = Zug / turnout * 100,
Mir_perc = Mir / turnout * 100,
Pro_perc = Pro / turnout * 100,
Put_perc = Put / turnout * 100)
Создадим переменную reg_type (тип региона), которая принимает значения “область”, “республика”, “край”, “округ”, “город”. Сразу получить такую переменную не получится (нужны конструкции с условиями и циклы, а мы пока их не обсуждали), но можно поступить по-другому – сначала создать дамми-переменные для каждого типа региона, а затем их скомбинировать.
Что такое дамми-переменная (фиктивная переменная)? Переменная, которая принимает значение 1, если выполняется определенное условие, и значение 0 во всех остальных случаях. В нашем примере нам необходимо создать целый набор взаимоисключающих дамми-переменных: для республик, для областей, для округов, для краев и для городов (городов федерального значения). Давайте для простоты пока опустим автономную область (почему так проще, чуть позже поймем, а на семинаре сделаем все, как надо).
Для поиска значений в текстовом векторе (столбце region) воспользуемся функцией grepl()
. Работает она так: ходит по элементам вектора, если элемент содержит текст, который мы ищем (паттерн, частичное совпадение), то функция выдает TRUE, если нет – FALSE, и так для всех элементов. Например:
regs <- c("Белгородская область", "Владимирская область", "Кабардино-Балкарская Республика", "Город Москва")
grepl(pattern = "область", regs)
## [1] TRUE TRUE FALSE FALSE
Видно, что функция grepl
выдает логический вектор из TRUE и FALSE. Чтобы получить дамми-переменную из 0 и 1, нужно превратить этот вектор в целочисленный:
as.integer(grepl(pattern = "область", regs))
## [1] 1 1 0 0
А теперь проделаем эти операции для разных типов регионов в нашей базе:
aggr_reg <- aggr_reg %>% mutate(resp = as.integer(grepl(pattern = "Республика", region)),
oblast = as.integer(grepl(pattern = "область", region)),
okrug = as.integer(grepl(pattern = "округ", region)),
krai = as.integer(grepl(pattern = "край", region)),
gorod = as.integer(grepl(pattern = "Город", region)))
View(aggr_reg)
Осталось скомбинировать полученные дамми-переменные – создать переменную reg_type:
aggr_reg$reg_type <- names(aggr_reg[15:19])[max.col(aggr_reg[15:19])]
Посмотрим на нашу базу данных:
View(aggr_reg)
Все получилось так, как и хотели. Но строчка с кодом выглядит для комбинации дамми-переменных выглядит загадочно. Чтобы разобраться, как она работает, посмотрим, каким образом мы “схлопываем” дамми-переменные. Последовательность действий такая.
Код ниже – для иллюстрации. Но с ним можно самим разобраться, работать с матрицами мы умеем.
Шаг 1. У нас есть примерно такая база данных:
## gorod krai oblast okrug resp
## Алтайский край 0 1 0 0 0
## Город Москва 1 0 0 0 0
## Ивановская область 0 0 1 0 0
## Республика Коми 0 0 0 0 1
## Ненецкий автономный округ 0 0 0 1 0
Шаг 2. Заменяем единички на названия столбцов, в котором они стоят:
## gorod krai oblast okrug resp
## Алтайский край 0 krai 0 0 0
## Город Москва gorod 0 0 0 0
## Ивановская область 0 0 oblast 0 0
## Республика Коми 0 0 0 0 resp
## Ненецкий автономный округ 0 0 0 okrug 0
Шаг 3. А теперь создаем для названий отдельный столбец и переносим все наименования в него:
## gorod krai oblast okrug resp reg_type
## Алтайский край 0 krai 0 0 0 krai
## Город Москва gorod 0 0 0 0 gorod
## Ивановская область 0 0 oblast 0 0 oblast
## Республика Коми 0 0 0 0 resp resp
## Ненецкий автономный округ 0 0 0 okrug 0 okrug
Функция max.col()
для каждой строки матрицы возвращает номер столбца, в котором находится максимальное значение по этой строке. В нашем случае – это номер столбца, где стоит единичка (так как всего два значения, 0 и 1):
max.col(m)
## [1] 2 1 3 5 4
В первой строке 1 стоит на втором месте, во второй – на первом и так далее.
Дальше на соответствующие единичкам позиции мы ставим названия столбцов (names()
) и собираем все в одну новую переменную reg_type
.
Как мы уже обсуждали, для описания качественных показателей мы можем использовать частоты (абсолютные или относительные – в долях или процентах).
Столбиковая диаграмма (bar plot)
Обычная столбиковая диаграмма в R строится не для самой переменной, а для таблицы частот. С таблицей частот мы уже знакомы:
table(aggr_reg$reg_type)
##
## gorod krai oblast okrug resp
## 2 9 45 3 19
Внимание: в этой базе данных есть не все регионы, будьте внимательны и осторожны.
Столбиковая диаграмма строится вот так:
barplot(table(aggr_reg$reg_type))
Диаграмма показывает, сколько регионов каждого типа в базе данных. Приведем график в порядок: добавим заголовок (main
), и более внятные подписи к столбикам (names.arg
).
barplot(table(aggr_reg$reg_type),
main = "Типы регионов",
names.arg = c("город фед. \n знач.", "край", "область", "округ", "республика"))
Символ \n
используется для переноса текста на новую строку – название слишком длинное и не хочется, чтобы оно перекрывало остальные подписи.
Поменяем цвет графика (col
) и добавим подпись к оси y (ylab
):
barplot(table(aggr_reg$reg_type),
main = "Типы регионов",
names.arg = c("город фед. \n знач.", "край", "область", "округ", "республика"),
col = "red",
ylab = "число регионов")
А теперь сделаем ось y более детальной – добавим побольше делений. Для ручной корректировки осей есть специальная функция axis()
, где первым аргументом идет номер оси (1 – для оси x, 2 – для оси y).
Внимание: строка с axis()
должна идти сразу после кода для построения самого графика, иначе R не поймет, к какому графику она относится, и выдаст ошибку.
Еще внимание: если “выправляем” оси с помощью axis()
, важно не забыть убрать оси на самом графике, иначе оси наложатся друг на друга, и это будет выглядеть странно.
# строим график
barplot(table(aggr_reg$reg_type),
main = "Типы регионов",
names.arg = c("город фед. \n знач.", "край", "область", "округ", "республика"),
col = "red",
ylab = "число регионов", axes = FALSE) # axes = FALSE - убираем оси
# корректируем оси
# at - где ставим деления
# здесь - от 0 до 50 через каждые 5 единиц
axis(2, at = seq(from = 0, to = 50, by = 5))
А что если мы захотим получить столбчатую диаграмму, но не с абсолютными частотами (число регионов), а с относительными частотами (в процентах)?
Все просто: чтобы построить такой график, нужно создать таблицу с частотами в процентах – взять таблицу, которую мы уже видели, поделить все частоты в ней на сумму значений и умножить на 100:
tab <- table(aggr_reg$reg_type)
perc <- tab/sum(tab) * 100
perc
##
## gorod krai oblast okrug resp
## 2.564103 11.538462 57.692308 3.846154 24.358974
barplot(perc)
А дальше приведем график в порядок:
# строим график
# ylim - границы значений по оси y (от 0 до 65)
barplot(perc,
main = "Типы регионов",
names.arg = c("город фед. \n знач.", "край", "область", "округ", "республика"),
col = "red",
ylim = c(0, 65),
ylab = "доля регионов (в %)",
axes = FALSE)
# корректируем оси
axis(2, at = seq(from = 0, to = 65, by = 5))
А чтобы было совсем здорово, добавим подписи с процентами на сам график. Для этого сначала создадим вектор с подписями – округлим значения в векторе perc и “приклеим” к каждому значению символ “%”.
perc_labels <- round(perc, 2) # округляем
perc_labels <- paste(perc_labels, "%", sep = "") # приклеиваем знак %
В paste()
мы добавили аргумент sep
, чтобы указать разделитель. По умолчанию разделителем является пробел, а мы хотим, чтобы перед знаком процента пробела не было.
Теперь нанесем все на график – добавим нужный нам текст (подписи).
Внимание: сначала нужно сохранить график в какую-нибудь переменную (pl), а затем указать ее в качестве аргумента функции text()
.
pl <- barplot(perc,
main = "Типы регионов",
names.arg = c("город фед. \n знач.", "край", "область", "округ", "республика"),
col = "red",
ylim = c(0, 65),
ylab = "доля регионов (в %)",
axes = FALSE)
# корректируем оси
axis(2, at = seq(from = 0, to = 65, by = 5))
# добавляем подписи
# x - положение текста по оси x (здесь - столбцы графика)
# y - положение текста по оси y (здесь - высота столбцов, проценты)
# pos = 3 - текст помещается над координатами (x, y)
text(x = pl, y = perc, labels = perc_labels, pos = 3)
На этом с наведением красоты можно закончить и перейти к другим графикам.
Круговая диаграмма (pie chart)
Круговая диаграмма строится для относительных частот – для процентов. Таблицу для процентов мы уже построили (perc).
pie(perc)
Пока выглядит грустно. Начинаем исправлять. Создадим вектор цветов для диаграммы:
# да, я специально подобрала нетипичные названия цветов
colors <- c('thistle2', 'plum2', 'palevioletred', 'orchid4', 'purple3')
pie(perc, col = colors)
Какие цвета есть в R можно посмотреть здесь.
Добавим внятные подписи (как и в случае столбчатой диаграммы).
labs = c("город федерального \n значения", "край", "область", "округ", "республика")
# в отличие от barplot, для надписей используем аргумент labels
pie(perc, col = colors, main = "Типы регионов", labels = labs)
Сильно красивее не стало.
Поэтому сделаем по-другому: на самом графике подпишем проценты (perc_labels), а остальное вынесем в легенду графика.
Внимание: как в случаях с axis()
и text()
прописываем код для легенды legend()
сразу после построения графика.
pie(perc, col = colors, main = "Типы регионов", labels = perc_labels)
# легенда
# bottomleft - позиция легенды, нижний левый угол
# labs - названия, которые должны быть в легенде
# cex - размер шрифта для наименований в легенде, по умолчанию 1
# fill - цвета, соответствующие наименованиям
legend("bottomleft", labs, cex = 0.6, fill = colors)
Гистограмма (histogram)
Гистограмма – график, который иллюстрирует соответствие между значениями количественной переменной и частотой, с которыми эти значения встречаются в выборке.
Для начала построим самую простую гистограмму. Построим гистограмму для явки на выборы (по регионам).
hist(aggr_reg$turnout_perc)
Теперь сделаем ее красивой: добавим название графика и подзаголовок, поменяем цвет и подпишем оси.
hist(aggr_reg$turnout_perc,
col = "lightgreen",
main = "Выборы президента 2012 года",
xlab = "Явка (в %)",
ylab = "Частоты")
Что показывает эта гистограмма? Форму распределения явки на выборах. По гистограмме видно следующее:
При построении гистограмм можно задействовать важный параметр – breaks
, число “разбивок”, то есть “перегородок”, которые нужно взять, чтобы поделить упорядоченную выборку на равные интервалы. Нетрудно догадаться, что число самих равных интервалов всегда будет на 1 меньше, чем число “перегородок”.
Пример:
|2 2 | 3 5 | 6 8 | 9 10|
breaks = 5
число интервалов = 4 (число столбцов в гистограмме)
Сравним две гистограммы:
hist(aggr_reg$turnout_perc, breaks = 10, col = "lightgreen")
hist(aggr_reg$turnout_perc, breaks = 20, col = "lightgreen")
Гистограммы внешне отличаются друг от друга. Но, на самом деле, это одна и та же гистограмма, просто с разными интервалами разбивки. На первой гистограмме ширина столбца равна 5, а на второй – 2. Как правило, вопрос о том, какое число столбцов гистограммы взять, не возникает, потому что R автоматически подбирает подходящее число столбцов. (По умолчанию используется алгоритм Стёржеса, кому интересно почитать про различные алгоритмы, см. здесь, Number of bins and width). Да, это Википедия, но там есть ссылки на оригинальные статьи про способы разбивки).
Ящик с усами (boxplot)
С помощью ящика с усами также можно представить распределение количественного показателя. В отличие от гистограммы, ящик с усами позволяет явно увидеть описательные статистики, посчитанные по переменной. Подробнее см. здесь.
# sub - подзаголовок
boxplot(aggr_reg$Zug_perc,
col = "tomato",
main = "Процент голосов",
sub = 'Зюганов ("КПРФ")')
Ящик с усами позволяет также определить, есть ли в выборке нетипичные значения (выбросы, outliers), то есть значения, которые сильно отличаются от остальных. В нашем случае такие наблюдения есть (точки, которые располагаются за пределами “усов” графика). Есть регионы, где за Зюганова проголосовало слишком мало избирателей или наоборот, слишком много. К сожалению, с помощью стандартной функции boxplot()
мы не сможем отметить на графике, что это за регионы. Но к более “продвинутым” ящикам с усами мы еще вернемся, когда будем работать с библиотекой ggplot2
.
boxplot(aggr_reg$Zug_perc,
col = "tomato",
main = "Процент голосов",
sub = 'Зюганов ("КПРФ")')