[Перевод] Создание интерактивных графиков с R и Highcharts
Для создания красивых графиков в этой статье я воспользуюсь пакетом highcharter Джошуа Кунста, оболочкой для javascript-библиотеки Highcharts и Shiny.
Пожалуйста, учтите, что все продукты в этой библиотеке бесплатны для некоммерческого использования. Для коммерческих проектов и сайтов воспользуйтесь этим.
Пакет highcharter позволяет создавать графики типа Highcharts внутри R.
В пакете есть две основных функции:
highchart()
: создает объект-график Highchart с помощью htmlwidgets. Виджет можно отобразить на HTML-страницах, созданных в R Markdown, Shiny или других приложениях.hchart()
: используетhighchart()
, чтобы одной простой командой нарисовать график для разных классов объектов в R. В частности, таких: data frame, numeric, histogram, character, density, factor, ts, mts, xts, stl, ohlc, acf, forecast, mforecast, ets, igraph, dist, dendrogram, phylo и survfit.
Графики строятся в духе ggplot2 по слоям, но используют оператор конвеера (%>%) вместо +.
Другие полезные функции пакета:
- Темизация: можно настроить графики с помощью встроенных тем, например, Economist, Financial Times, Google и FiveThirtyEight.
- Расширения: motion, drag points, fontawesome, url-pattern, annotations.
Проиллюстрируем функциональность этого пакета и Highcharts в целом рядом примеров-визуализаций.
Пример 1: Родившиеся в пятницу, 13-го, в США
На эту визуализацию меня вдохновила статья в FiveThirtyEight «Некоторые слишком суеверны, чтобы рожать в пятницу, 13-го». FiveThirtyEight любезно предоставляет данные, использующиеся в некоторых статьях, в репозитории на GitHub. Конкретно эти — отсюда.
Наша цель — воссоздать именно эту визуализацию. Для того, чтобы это сделать, необходимо подсчитать разницу между количеством родившихся 13-го и среднее для 6-го и 20-го числа каждого месяца, группируя эти значения по дням недели. С этим прекрасно справятся dplyr и tidyr.
Загрузим необходимые пакеты:
library(highcharter)
library(dplyr)
library(tidyr)
И данные:
births <- read.csv("data/births.csv")
Посчитаем разницы в количестве родившихся, как описано в статье, и сохраним результаты в новый пакет данных (data frame)
diff13
: diff13 <- births %>%
filter(date_of_month %in% c(6, 13, 20)) %>%
mutate(day = ifelse(date_of_month == 13, "thirteen", "not_thirteen")) %>%
group_by(day_of_week, day) %>%
summarise(mean_births = mean(births)) %>%
arrange(day_of_week) %>%
spread(day, mean_births) %>%
mutate(diff_ppt = ((thirteen - not_thirteen) / not_thirteen) * 100)
Который выглядит так:
## Source: local data frame [7 x 4]
## Groups: day_of_week [7]
##
## day_of_week not_thirteen thirteen diff_ppt
##
## 1 1 11658.071 11431.429 -1.9440853
## 2 2 12900.417 12629.972 -2.0964008
## 3 3 12793.886 12424.886 -2.8841902
## 4 4 12735.145 12310.132 -3.3373249
## 5 5 12545.100 11744.400 -6.3825717
## 6 6 8650.625 8592.583 -0.6709534
## 7 7 7634.500 7557.676 -1.0062784
Обратите внимание, что рассчитанный процент разниц в процентных пунктах (
diff_ppt
) может не соответствовать приведенному в статье FiveThirtyEight. На то есть две причины: - В FiveThirtyEight исключены праздники, а в этом анализе — нет.
- FiveThirtyEight предоставляют два файла с данными — за 1994–2003 и за 2000–2014 годы соответственно. Количество родившихся в пересекающихся годах (2000–2003) в этих файлах не совсем совпадает. Это приложение использует данные Администрации социального обеспечения (SSA, Social Security Administration) за соответствующие годы, но непонятно, какими данными воспользовались FiveThirtyEight.
Начнем с простенького highchart для этих данных с помощью функции
hchart()
: hchart(diff13, "scatter", x = day_of_week, y = diff_ppt)
У этого графика есть ряд хороших свойств. Например, если навести мышкой на точки, можно увидеть фактические значения, взятые для построения. Однако, для того, чтобы график выглядел, как в FiveThirtyEight, понадобится определенная настройка. Этого можно добиться с помощью функции
highchart()
и некоторых других. Обратите внимание, мы разделяем слои оператором конвеера.highchart() %>%
hc_add_series(data = round(diff13$diff_ppt, 4), type = "column",
name = "Difference, in ppt",
color = "#F0A1EA", showInLegend = FALSE) %>%
hc_yAxis(title = list(text = "Difference, in ppt"), allowDecimals = FALSE) %>%
hc_xAxis(categories = c("Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday"),
tickmarkPlacement = "on",
opposite = TRUE) %>%
hc_title(text = "The Friday the 13th effect",
style = list(fontWeight = "bold")) %>%
hc_subtitle(text = "Difference in the share of U.S. births on 13th of each month
from the average of births on the 6th and the 20th,
1994 - 2004") %>%
hc_tooltip(valueDecimals = 4,
pointFormat = "Day: {point.x}
Diff: {point.y}") %>%
hc_credits(enabled = TRUE,
text = "Sources: CDC/NCHS, SOCIAL SECURITY ADMINISTRATION",
style = list(fontSize = "10px")) %>%
hc_add_theme(hc_theme_538())
Заголовок: Эффект пятницы, 13-го
Подзаголовок: Разница в количестве родившихся в США 13-го числа каждого месяца и среднего количества родившихся 6-го и 20-го, 1994 — 2004
Метки по оси 0Х: понедельник, вторник, среда, четверг, пятница, суббота, воскресенье
Подпись по оси 0Y: Разница, в процентных пунктах
Полезное свойство в этой визуализации — тоже всплывающая подсказка. Также темы позволяют легко поменять внешний вид графика (в этом случае тема hc_theme_538()
сильно приближает нас к оригиналу). Еще можно легко менять метки (например, названия дней) без внесения изменений в исходные данные.
Пример 2: Родившиеся в пятницу, 13-го, в США, интерактивность
Поскольку пакет highcharter использует htmlwidlgets, он также совместим с Shiny. Для того, чтобы построить highchart внутри приложения на Shiny, используют функцию
renderHighchart()
.Мы написали приложение, расширяющее созданную ранее визуализацию и позволяющее настраивать диапазон лет, для которых берутся данные на графике, его тип и тему. Скриншот приведен ниже, а само приложение и его исходный код можно посмотреть здесь.
Чего стоит опасаться
Наиболее привлекательные функции highcharts — встроенная и настраиваемая всплывающая подсказка и масштабирование. Но будут ли эти функции полезны, зависит от каждого конкретного случая.
Например, всплывающие подсказки не настолько хороши, если строить график по данным большего объема. Посмотрите на этот график задержек приземлений и вылетов рейсов в Лос-Анджелес в октябре 2013 в разных аэропортах Нью-Йорка. Скопление точек в левой нижней части графика делает всплывающие подсказки не такими удобными.
library(nycflights13)
oct_lax_flights <- flights %>%
filter(month == 10, dest == "LAX")
hchart(oct_lax_flights, "scatter", x = dep_delay, y = arr_delay, group = origin)
Но если немного сгруппировать данные, чтобы уменьшить количество точек, эта функциональность снова может пригодиться. Например, ниже мы группируем рейсы по 15-минутным интервалам в задержке вылета и выводим медиану задержки приземления для этих интервалов.
oct_lax_flights_agg <- oct_lax_flights %>%
mutate(dep_delay_cat = cut(dep_delay, breaks = seq(-15, 255, 15))) %>%
group_by(origin, dep_delay_cat) %>%
summarise(med_arr_delay = median(arr_delay, na.rm = TRUE))
hchart(oct_lax_flights_agg, "line", x = dep_delay_cat, y = med_arr_delay, group = origin)
Заключение
Highcharts предоставляет веб-графику отличного качества с возможностью тонкой настройки, и пакет highcharter дает возможность пользователям R в полной мере этим воспользоваться. Если вас заинтересовали функции, доступные в пакете, очень рекомендую заглянуть на страницу пакета highcharter: там есть множество графиков Highcharts, Highstock и Highmaps с примерами кода. Также, если нужно проверить синтаксис каких-то настроек, чрезвычайно полезна страница с описанием опций Highcharts.