Анимированные гистограммы, которые можно встроить прямо в публикацию на любом сайте, становятся все более популярными. Они отображают динамику изменений любых характеристик за определенное время и делают это наглядно. Давайте посмотрим, как их создать при помощи R и универсальных пакетов.
Skillbox рекомендует: Практический курс «Python-разработчик с нуля».
Напоминаем: для всех читателей «Хабра» — скидка 10 000 рублей при записи на любой курс Skillbox по промокоду «Хабр».
Пакеты
Нам нужны пакеты в R:
- ggplot2
- gganimate
Эти два крайне необходимы. Кроме того, потребуются tidyverse, janitor и scales для управления данными, очистки массива и форматирования соответственно.
Данные
Оригинальный набор данных, который мы будем использовать в этом проекте, загружается с сайта Всемирного банка. Вот они — WorldBank Data. Те же данные, если они вам нужны в готовом виде, можно загрузить из папки проекта.
Что это за информация? Выборка содержит значение ВВП большинства стран за несколько лет (с 2000 по 2017 годы).
Обработка данных
Мы будем использовать код, размещенный ниже, для подготовки необходимого формата данных. Очищаем названия столбцов, превращаем цифры в числовой формат и конвертируем данные при помощи функции gather(). Все, что получено, сохраняем в gdp_tidy.csv для дальнейшего использования.
library(tidyverse)
library(janitor)
gdp <- read_csv("./data/GDP_Data.csv")
#select required columns
gdp <- gdp %>% select(3:15)
#filter only country rows
gdp <- gdp[1:217,]
gdp_tidy <- gdp %>%
mutate_at(vars(contains("YR")),as.numeric) %>%
gather(year,value,3:13) %>%
janitor::clean_names() %>%
mutate(year = as.numeric(stringr::str_sub(year,1,4)))
write_csv(gdp_tidy,"./data/gdp_tidy.csv")
Анимированные гистограммы
Их создание требует двух этапов:
- Построение полного набора актуальных гистограмм с использованием ggplot2.
- Анимирование статических гистограмм с желаемыми параметрами при помощи gganimate.
Финальный шаг — рендеринг анимации в желаемом формате, включая GIF или MP4.
Загрузка библиотек
- library(tidyverse)
- library(gganimate)
Управление данными
На этом шаге надо отфильтровать данные для получения топ-10 стран каждого года. Добавим несколько колонок, которые позволят отображать легенду для гистограммы.
gdp_tidy <- read_csv("./data/gdp_tidy.csv")
gdp_formatted <- gdp_tidy %>%
group_by(year) %>%
# The * 1 makes it possible to have non-integer ranks while sliding
mutate(rank = rank(-value),
Value_rel = value/value[rank==1],
Value_lbl = paste0(" ",round(value/1e9))) %>%
group_by(country_name) %>%
filter(rank <=10) %>%
ungroup()
Построение статических гистограмм
Теперь, когда у нас есть пакет данных в нужном формате, начинаем отрисовку статических гистограмм. Базовая информация — топ-10 стран с максимальным ВВП за выбранный интервал времени. Графики строим для каждого года.
staticplot = ggplot(gdp_formatted, aes(rank, group = country_name,
fill = as.factor(country_name), color = as.factor(country_name))) +
geom_tile(aes(y = value/2,
height = value,
width = 0.9), alpha = 0.8, color = NA) +
geom_text(aes(y = 0, label = paste(country_name, " ")), vjust = 0.2, hjust = 1) +
geom_text(aes(y=value,label = Value_lbl, hjust=0)) +
coord_flip(clip = "off", expand = FALSE) +
scale_y_continuous(labels = scales::comma) +
scale_x_reverse() +
guides(color = FALSE, fill = FALSE) +
theme(axis.line=element_blank(),
axis.text.x=element_blank(),
axis.text.y=element_blank(),
axis.ticks=element_blank(),
axis.title.x=element_blank(),
axis.title.y=element_blank(),
legend.position="none",
panel.background=element_blank(),
panel.border=element_blank(),
panel.grid.major=element_blank(),
panel.grid.minor=element_blank(),
panel.grid.major.x = element_line( size=.1, color="grey" ),
panel.grid.minor.x = element_line( size=.1, color="grey" ),
plot.title=element_text(size=25, hjust=0.5, face="bold", colour="grey", vjust=-1),
plot.subtitle=element_text(size=18, hjust=0.5, face="italic", color="grey"),
plot.caption =element_text(size=8, hjust=0.5, face="italic", color="grey"),
plot.background=element_blank(),
plot.margin = margin(2,2, 2, 4, "cm"))
Строить графики с использованием ggplot2 весьма просто. Как вы можете видеть в участке кода выше, есть несколько ключевых моментов с функцией theme (). Они необходимы, чтобы все элементы анимировались без проблем. Некоторые из них можно и не отображать при необходимости. Пример: прорисовываются только вертикальные линии сетки и легенды, а вот заголовки осей и еще несколько компонентов удаляются с участка.
Анимация
Ключевая функция здесь — transition_states(), она склеивает отдельные статические графики. view_follow () используется для прорисовки линий сетки.
anim = staticplot + transition_states(year, transition_length = 4, state_length = 1) +
view_follow(fixed_x = TRUE) +
labs(title = 'GDP per Year : {closest_state}',
subtitle = "Top 10 Countries",
caption = "GDP in Billions USD | Data Source: World Bank Data")
Рендеринг
После того, как анимация создана и сохранена в объекте anim, приходит время ее визуализировать с помощью функции animate (). Рендерер, используемый в animate (), может быть разным в зависимости от типа требуемого выходного файла.
GIF
# For GIF
animate(anim, 200, fps = 20, width = 1200, height = 1000,
renderer = gifski_renderer("gganim.gif"))
MP4
# For MP4
animate(anim, 200, fps = 20, width = 1200, height = 1000,
renderer = ffmpeg_renderer()) -> for_mp4
anim_save("animation.mp4", animation = for_mp4 )
Результат
Как видим, ничего сложного. Весь проект доступен в моем GitHub, можете использовать его так, как посчитаете нужным.
Skillbox рекомендует:
- Двухлетний практический курс «Я — веб-разработчик PRO».
- Онлайн-курс «С#-разработчик с нуля».
- Практический годовой курс «PHP-разработчик с 0 до PRO».
Автор: fokus-lop