Это начало серии заметок о возможностях ggplot2. Начнём с простого - нарисуем пару линий на плоскости, разберёмся с тем, как устроен интерфейс библиотеки ggplot2. Также по ходу дела немного затронем вопрос о выгрузке и обработке данных в R.
Сегодня мы научимся:
- Делать линейные графики с кастомными цветами.
- Добавлять собственные шрифты.
- Изменять разметку, оси координатб легенду.
- Добавлять посторонние тематические изображения в ggplot.
- Как сохранить график, чтобы было красиво и ничего не поломалось.
library(tidyverse) # Обработка данных
library(readxl) # Работа с excel файлами в R
library(showtext) # Рендер текста в ggplot2
library(sysfonts) # загрузка шрифтов в R
library(png) # работа с изображениями
library(grid) # работа с изображениями
library(gridExtra) # работа с изображениями
library(httr) # Скачать файлы из сети
showtext_auto() # рендер текста в ggplot при помощи showtext
# Я залил все варианты шрифта HSE Sans в github. теперь их можно удобно скачать в директорию и загрузить в R.
GET('https://github.com/ETymch/Econometrics_2023/raw/main/Plotting/HSESans-Regular.otf', write_disk('HSESans-Regular.otf', overwrite = T)) # Загрузка HSE Sans Regular, самого красивого шрифта.
font_add(family = 'HSE Sans', regular = "HSESans-Regular.otf") # Установка HSE Sans Regular.
Чтобы попрактиковаться в выборе цветов в работе с изображениями нам лучше заранее всё подготовить. Для начала, я выбрал два кофейный цвета, их мы будем использовать при построении графика. Также нам часто нужно вставить на график картинку (я выбрал картинку с падающими зёрнами кофе) - это легко и просто. Для этого загрузим из сети изображение и обработаем его.
# Цвета
coffee_1 <- '#4B1F0E' # Чёрный кофе
coffee_2 <- '#BE7656' # Кофе со сливками
# Картинка
alpha = 0.2 # Коэффициент прозрачности
GET('https://github.com/ETymch/Econometrics_2023/blob/main/Pics/coffee.png?raw=true', write_disk('coffee.png', overwrite = T)) # Загрузка изображения из сети
beans <- png::readPNG('coffee.png') # Загрузка изображения в R
beans <- matrix(rgb(beans[,,1], beans[,,2], beans[,,3], beans[,,4] * alpha), nrow = dim(beans)[1]) %>%
rasterGrob() # сделать изображение прозрачным с коэффициентом alpha.
Обработка данных - самый сложный этап при построении графиков. Чем больше вы будете пользоваться R - тем быстрее и легче вам будет это даваться. Практикуйтесь чаще, не пасуйте, гуглите (я постоянно чтото забываю и гуглю), всё получится. Используйте tidy approach и pipes %>%
- так вам и другим людям будет проще писать и редактировать код.
httr::GET('https://github.com/ETymch/Econometrics_2023/raw/main/Datasets/CMO-Historical-Data-Monthly.xlsx', httr::write_disk('Commodities.xlsx', overwrite = T)) # Загрузка файла с данными.
## Response [https://raw.githubusercontent.com/ETymch/Econometrics_2023/main/Datasets/CMO-Historical-Data-Monthly.xlsx]
## Date: 2023-09-19 14:46
## Status: 200
## Content-Type: application/octet-stream
## Size: 752 kB
## <ON DISK> C:\Users\evgen\econometrics_2023\Econ_site\content\gg\Commodities.xlsx
# Обработка данных
data <- read_excel('Commodities.xlsx', sheet = 2, skip = 6) %>% # Загрузка сырого эксельного файла. Нам нужен второй лист. Чтобы пропустить 6 строк до нужной нам таблички используем skip.
select(...1, COFFEE_ARABIC, COFFEE_ROBUS) %>% # Выбираем интересующие нас данные
rename(c('Дата' = '...1', # Переименовываем столбцы
'Арабика' = 'COFFEE_ARABIC',
'Робуста' = 'COFFEE_ROBUS')) %>%
mutate(Дата = seq(as.Date('1960-01-01'), length.out = length(Дата), by = 'month')) %>% # Заменяем столбец с данными на ряд в формате `Дата` с началом в 1960, с длиной такой же, как наш столбец с датами, с шагом в месяц.
pivot_longer(Арабика:Робуста) # преобразуем в длинную таблицу. Так удобнее для рисования
Самая важная и интересная часть материала - построение графика. Чтобы не растягивать до бесконечности данную часть, я опишу, как лучше работать с кодом, чтобы получить понимание, как устроен ggplot2. Так вам будет проще самостоятельно строить графики в будущем.
- Посмотрите внимательно на то, как выглядит таблица data, как она устроена. Так вам будет проще понять аргументы (aes) в функции ggplot, когда мы начнём строить график.
- Прочитайте все комментарии к коду.
- В материале я даю итоговую версию графика. Но это не значит, что нужно начинать с неё. Скопируйте первые три строчки кода (без последнего плюсика) в своё окно, запустите эти три строчки кода. Посмотрите на результат.
- Поиграйтесь с параметрами size (любое положительное число) и alpha (от 0 до 1).
- Постепенно добавляйте к вашему коду по одной строчке, смотрите, что меняется.
- В 4 строке попробуйте изменить цвета линий. Используйте hex коды.
- В пятой строке попробуйте передвинуть изображение вправо, влево, вверх, вниз, сделать его меньше…
- Измените тему 6 строке. Попробуйте
theme_bw()
,theme_ft()
,theme_void()
,theme_classic()
. Попробуйте не выбирать основной шрифт, оставить аргументы функции пустыми. Попробуйте выбрать другой основной шрифт. - Попробуйте сделать так, чтобы легенда отображалась сверху.
legend.position = 'top'
. Убрать легенду вовсе -legend.position = 'none'
- Попробуйте изменить положение сетки:
plot.grid...
. - Попробуйте изменить положение названия графика, подзаголовка, ссылок.
data %>% # Используем pipe. Он делает data первым в функции ggplot в следующей строке
ggplot(aes(x = Дата, y = value, color = name)) + # Хороший стиль в ggplot - описывать все аргументы в начале. Их у нас 3. x - то, что мы хотим начертить по горизонтальной оси, у - по вертикальной оси, color - разбивка линий по цветам
geom_line(size = 0.8, alpha = 0.6) + # геометрия которую мы используем
scale_color_manual(values = c(coffee_1, coffee_2)) + # цвета
annotation_custom(beans, xmin = as.Date('1960-01-01'), xmax = as.Date('2022-01-01'), ymin = 0.5, ymax = 7) + # прозрачная картинка с зёрнами
theme_minimal(base_family = 'HSE Sans') + # тема
theme(legend.position = 'bottom', # сделаем тему ещё красивее, легенду - вниз.
legend.title = element_blank(), # убрать название легенды
panel.grid.major.x = element_blank(), # Сейчас модно делать графики с малым количеством разметки. Давайте уберём все вертикальные линии.
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(), # Уберём часть горизонтальной разметки. Так график выглядит аккуратнее.
plot.title = element_text(hjust = 0.5, size = 15), # Вы, наверное, заметили, что изначально ggplot отображает название слева. Давайте переместим его в центр.
plot.subtitle = element_text(hjust = 0.5, size = 12) # То же проделаем и с подзаголовком
) +
labs(y = 'Долл. / кг', # Названия осей, заголовки, ссылки
x = '', # ось x
title = 'Цены на мировом рынке кофе', # Заголовок
subtitle = '1960-2023', # Подзаголовок
caption = 'World Bank Commodity Price Data', # Сноска
)
Чтобы сохранить график я предпочитаю формат svg. Он позволяет передать высокое качество и не заморачиваться с размерами шрифтов и линий, которые съезжают, если сохранять в png
с разным dpi
.
ggsave('coffee_plot_final.svg')