Календарные диаграммы в R

Временные ряды являются специфическими массивами. При их графическом отображении следует учитывать то, что одна из координат графика уже “занята” осью времени. Поэтому наглядно представить данные временного ряда иногда довольно затруднительно. Особые трудности возникают, когда данные нужно отобразить с высоким разрешением и за длительный период времени, например: каждый день за последние несколько лет. Именно графическое отображение такого временного ряда мы рассмотрим в этой статье. И пользоваться при этом мы будем возможностями нескольких восхитительных пакетов превосходной программной среды R. А для реализации всех безграничных возможностей будем пользоваться средой разработки RStudio.
В качестве исходных данных возьмём “подчищенный” архив метеорологических наблюдений нескольких метеостанций. Нас интересует метестанция международного аэропорта “Кривой Рог” (“Лозоватка”). Конечным результатом нашей работы будет “календарная диаграмма” – классический календарь в чистом виде с отображением в каждом дне суточной изменчивости относительной влажности воздуха.
Для начала “сверим часы” – посмотрим параметры операционной системы и информацию про сам R. Это можно сделать с помощью команды:

sessionInfo()
R version 3.2.0 (2015-04-16)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Debian GNU/Linux stretch/sid
locale:
[1] LC_CTYPE=uk_UA.UTF-8 LC_NUMERIC=C LC_TIME=uk_UA.UTF-8
[4] LC_COLLATE=uk_UA.UTF-8 LC_MONETARY=uk_UA.UTF-8 LC_MESSAGES=uk_UA.UTF-8
[7] LC_PAPER=uk_UA.UTF-8 LC_NAME=C LC_ADDRESS=C
[10] LC_TELEPHONE=C LC_MEASUREMENT=uk_UA.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] ggplot2_1.0.1 dplyr_0.4.1

Установлен R версии 3.2.0 в операционной системе Debian GNU/Linux (тестовая версия “sid”). Процессор архитектуры x86_64. Далее следует информация о локальных настройках пользователя и списки загруженных в рабочее пространство пакетов. Кроме базовых пакетов (stats, graphics и др.), в рабочее пространство загружены пакеты ggplot2 и dplyr. Именно этими пакетами мы воспользуемся для подготовки данных и построения нашей диаграммы. Для взаимодействия между командами мы будем использовать “конвейер” (команда %>%), чтобы не плодить большое количество временных таблиц и векторов. Конвейер передаёт выход одной функции на вход другой функции. За счёт этого устраняется необходимость сохранения промежуточного результата в виде отдельного объекта.

Начнём! Таблица с метеорологическими наблюдениями уже загружена в наше рабочее пространство в виде data.frame “bigmeteo”. В таблице присутствует три поля: punkt – условное название метеорологической станции, date2 – дата и время проведения наблюдения, U – значение относительной влажности воздуха (%).

Однако, нужно оговорить одно условие – изначально в моей таблице поле date2 отформатировано в виде даты формата POSIXlt/POSIXt. Это сделано для удобства работы с другими функциями и другими пакетами. Но пакет dplyr “плохо переваривает” такой формат. Чтобы не проводить “на лету” многочисленные переформатирования – я использую команду filter после того, когда временная рабочая таблица уже сформирована. После этого я просто удаляю поле в формате даты POSIXlt/POSIXt. Для больших данных такой подход весьма нерационален. Нам стоило бы сначала “вырезать” данные по интересующей нас метеостанции, а потом уже плодить новые поля в таблице. Но для нашей размерности исходной таблицы (всего 99932 записи и 3 поля) такой подход ещё вытерпеть можно. Когда Вы загрузите таблицу данных в своё рабочее пространство, то чтобы получить дату в вышеназванном формате POSIX, Вы должны выполнить команду:

bigmeteo$date2 <- strptime(as.character(bigmeteo$date2), format = "%Y-%m-%d %H:%M:%S",  tz = "Europe/Kiev")

Далее – загружаем пакеты dplyr и ggplot2:

library(dplyr)
library(ggplot2)

Теперь приводим основную рабочую часть кода:

png("diadramma.png", width = 297, height = 210, units = "mm", res = 150) #сразу включаем экспорт в файл PNG формата А4
tbl_df(bigmeteo) %>% #переводим data.frame в формат пакета dplyr и загоняем "в конвейер"
mutate(year = as.numeric(format(date2, "%Y")), #создаём поле "год"
month.order = ordered(format(date2, "%B"), levels = c("січень", "лютий", "березень", "квітень", "травень", "червень", "липень", "серпень", "вересень", "жовтень", "листопад", "грудень")), #создаём факторное поле "месяц" и присваиваем ему уровни. Это нужно для правильной последовательности месяцев на диаграмме
weekday.order = ordered(format(date2, "%a"), levels = rev(c("пн", "вт", "ср", "чт", "пт", "сб", "нд"))), #создаём факторное поле "день недели" и присваиваем ему уровни
day.month = as.integer(format(date2, "%d")), #создаём поле "день месяца" (номер дня)
year.month = format(date2, "%h %Y"), #создаём поле "месяц с годом" с сокращённым названием месяца и полным номером года
week = as.numeric(format(date2, "%W")), #создаём поле "номер недели в году"
tmp_date = as.Date(format(date2, "%Y%m%d"), "%Y%m%d")) %>% #создаём рабочее поле "дата" (год-месяц-день), закрываем функцию mutate и передаём массив дальше по конвейеру
select(-date2) %>% #удаляем поле с датой в формате POSIXlt/POSIXt
filter(punkt == "Лозоватка") %>% #выбираем нужную метеостанцию
group_by(year.month, tmp_date) %>% #группируем массив по полям "месяц с годом" и "дата"
mutate(Uiqr = IQR(U, na.rm = TRUE)) %>% #создаём для каждого значения даты поле "изменчивость". В качестве показателя изменчивости используем интерквартильный размах (IQR) значений влажности воздуха за каждые сутки
group_by(year.month) %>% #группируем массив по полю "месяц с годом"
mutate(monthweek = 1+week-min(week)) %>% #создаём поле "неделя месяца"
ggplot(aes(monthweek, weekday.order, fill = Uiqr))+ #вызываем функцию ggplot для построения графика
geom_tile(colour = "white")+ #указываем тип графика
facet_grid(year~month.order)+ #дробим график по полям "год" и "месяц"
scale_fill_gradient2(name = "Інтерквартильний розмах: ", limits = c(0, 60), low = "royalblue3", mid = "gold2", high = "orangered3", midpoint = 30)+ #настраиваем градиент заливки и подпись к легенде
scale_x_continuous(breaks=seq(1, 6, 1))+ #задаём отображение недель месяца по оси X
labs(y = "день тижня", x = "тиждень місяця", title = "Мінливість відносної вологості повітря\nза даними метеостанції міжнародного аеропорту «Кривий Ріг»")+ #задаём подписи осей и заголовок
theme(text = element_text(family = "Liberation Serif", face = "italic", size = 15, colour = "orangered4", lineheight = 0.8), legend.position = "bottom", legend.text = element_text(family = "Liberation Serif", face = "italic", size = 9, colour = "orangered4", lineheight = 0.8), axis.text = element_text(colour = "gray15", face="bold"), axis.ticks = element_line(colour = "orange", size = 0.2), plot.background = element_rect(fill = "gray95"), panel.grid.major = element_line(colour = "orange", size = 0.2), panel.grid.minor = element_line(colour = "gray95"), panel.background = element_rect(fill = "gray90"))+ #настройки цветов и шрифтов элементов графика
geom_text(aes(label = day.month), position = position_identity(width = 0.9), vjust = 0.5, family = "Liberation Serif", face = "bold", size = 2.6, colour = "orangered4") #задаём отображение чисел для каждого месяца в ячейках графика
dev.off() #закрываем графическое устройство для сохранения графика в файл


Результатом выполнения этого кода будет создание в Вашей рабочей директории подобной диаграммы:

Мінливість відносної вологості повітря за даними метеостанції міжнародного аеропорту "Кривий Ріг"

Мінливість відносної вологості повітря за даними метеостанції міжнародного аеропорту “Кривий Ріг”

Много? Зато гибко и настраиваемо!

Давайте теперь рассмотрим некоторые нюансы. Во-первых – у меня в системе установлена гарнитура Liberation Serif, и она мне нравится. Вы можете выбрать любую другую. Однако не забывайте – шрифты отличаются начертанием и размером букв. Вам придётся немного поиграться с размерами символов (параметр size субкоманды element_text), чтобы достичь красивого вида диаграммы. В принципе, команда theme – всего-лишь “наведение рюшечек” на готовую диаграмму. От неё вполне можно отказаться. Такими же “рюшечками” является и последняя команда geom_text, где мы вставляем числа месяца внутрь графика. Может она вообще является перебором. Решать Вам!

Второй вопрос – как я определил граничные значения для заливки? Всё очень просто! Перед построением диаграммы я выполнил только часть кода и временно вписал в последнюю выполняемую строку (перед самой передачей по конвейеру на ggplot) команду summary:

mutate(Uiqr = IQR(U, na.rm = TRUE)) %>% #создаём для каждого значения даты поле "изменчивость"...
group_by(year.month) %>% #группируем массив по полю "месяц с годом"
mutate(monthweek = 1+week-min(week)) %>% summary()

Выполнение команды summary выведет нам на экран основные параметры нашей новой таблицы (которая существует лишь виртуально). Из вывода summary Вы узнаете о минимальном и максимальном значении переменной Uiqr. Только не забудьте удалить эту команду перед построением диаграммы!

Если Вам понравилась статья – можете поблагодарить автора небольшим пожертвованием на кошельки WebMoney Z237214434315, U396004717050 либо R337925998765; или же на карту ПриватБанка 5167982301844061

2 Comments

  1. Pingback: Дещо з візуалізації часових рядів в R | DataStory

  2. Pingback: Интерполяция и объединение временных рядов в R – DataStory

Leave a Comment

%d блогерам подобається це: