Материалы для самостоятельного изучения

Пакеты {stringr} и {ggplot2}

Автор

Анна Валяева

Дата публикации

20 сентября 2024 г.

Работа со строками со {stringr}

Тип строка (character, chr) может хранить как один или несколько символов, одно слово, так и целые предложения или абзацы текста. Чтобы понять, что перед вами строка, можно обратить внимание на кавычки или переспросить у R тип данных с помощью функции typeof().

chr_variable
[1] "ФББ МГУ"
typeof(chr_variable)
[1] "character"

Чтобы создать строку, необходимо заключить слово (набор символов) в кавычки - без разницы одинарные или двойные. Если строка должна содержать кавычки, то нужно использовать разные кавычки для обозначения строки и внутри строки.

"Курс для студентов ФББ 'Язык R и его применение в биоинформатике'"
[1] "Курс для студентов ФББ 'Язык R и его применение в биоинформатике'"

Также можно преобразовать другой тип данных в строки с помощью функции as.character().

as.character(c(F, T, T))
[1] "FALSE" "TRUE"  "TRUE" 

Чаще всего мы все же будем работать с наборами данных, собранных в виде таблиц - датафреймов. В них некоторые столбцы могут быть строковыми. Это можно заметить по подписи <chr> под названием столбца, если вы работаете с тибблом. Также строковые столбцы можно отобрать с помощью конструкции where(is.character()). Такие столбцы обычно содержат значения категориальных признаков или комментарии к конкретным записям.

starwars %>% select(where(is.character))
# A tibble: 87 × 8
   name           hair_color skin_color eye_color sex   gender homeworld species
   <chr>          <chr>      <chr>      <chr>     <chr> <chr>  <chr>     <chr>  
 1 Luke Skywalker blond      fair       blue      male  mascu… Tatooine  Human  
 2 C-3PO          <NA>       gold       yellow    none  mascu… Tatooine  Droid  
 3 R2-D2          <NA>       white, bl… red       none  mascu… Naboo     Droid  
 4 Darth Vader    none       white      yellow    male  mascu… Tatooine  Human  
 5 Leia Organa    brown      light      brown     fema… femin… Alderaan  Human  
 6 Owen Lars      brown, gr… light      blue      male  mascu… Tatooine  Human  
 7 Beru Whitesun… brown      light      blue      fema… femin… Tatooine  Human  
 8 R5-D4          <NA>       white, red red       none  mascu… Tatooine  Droid  
 9 Biggs Darklig… black      light      brown     male  mascu… Tatooine  Human  
10 Obi-Wan Kenobi auburn, w… fair       blue-gray male  mascu… Stewjon   Human  
# ℹ 77 more rows

Для работы со строками (поиск слова в строке, замена символов и т.д.) есть набор функций в “базовом” R, но пакет {stringr} из коллекции tidyverse предоставляет более удобный функционал. Чтобы иметь возможность работать с этим пакетом, достаточно установить (что у вас уже должно быть сделано) и подгрузить пакет {tidyverse} - library(tidyverse). Либо можно подгрузить только {stringr} без других tidyverse-пакетов (но они обычно пригождаются) - library(stringr).

library(tidyverse)

Практически все функции из пакета {stringr} начинаются со str_. После ввода этих символов в RStudio появляется окошко-подсказка со списком доступных функций - это очень удобно, ведь просто по названию функции можно легко понять или вспомнить, что эта функция делает, и быстро найти нужный вариант.

Далее рассмотрим несколько функций из пакета {stringr}. Список всех функций этого пакета можно получить с помощью команды help(package = stringr).

Будем работать с датафреймом starwars (набор данных из одного из пакетов tidyverse) и с вектором с названиями дней недели, который создадим сами:

weekdays <- c("Monday", "Tuesday", "Wednesday", "Thursday", 
              "Friday", "Saturday", "Sunday")
weekdays
[1] "Monday"    "Tuesday"   "Wednesday" "Thursday"  "Friday"    "Saturday" 
[7] "Sunday"   

Изменение регистра

Для изменения регистра букв в строках в {stringr} есть функции str_to_lower(), str_to_upper(), str_to_sentence() и str_to_title(). Первые две из них дублируют функции tolower() и toupper() из “базового” R.

str_to_title(chr_variable)
[1] "Фбб Мгу"

Длина строки

Длину строки (число символов в строке) можно получить с помощью функции str_length().

str_length(weekdays)
[1] 6 7 9 8 6 8 6

Важно осознать, что все функции из {stringr} можно применять не только к векторам, но и к строковым столбцам в датафремах, а именно использовать в сочетании с функциями из {dplyr} (например, mutate() или filter()) и в конвейерах.

starwars %>% 
  transmute(name, name_length = str_length(name))
# A tibble: 87 × 2
   name               name_length
   <chr>                    <int>
 1 Luke Skywalker              14
 2 C-3PO                        5
 3 R2-D2                        5
 4 Darth Vader                 11
 5 Leia Organa                 11
 6 Owen Lars                    9
 7 Beru Whitesun lars          18
 8 R5-D4                        5
 9 Biggs Darklighter           17
10 Obi-Wan Kenobi              14
# ℹ 77 more rows

Поиск слов или шаблонов в строке

В пакете {stringr} есть несколько функций, которые осуществляют поиск заданного слова (или шаблона) в строке.

  • str_detect() проверяет, содержит ли строка слово/шаблон и возвращает логический вектор.
str_detect(weekdays, "Sun") # содержит Sun
[1] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE
  • str_which() проверяет, содержит ли строка слово/шаблон и возвращает вектор с индексами строк, в которых совпадение нашлось.
str_which(weekdays, "Sun") # содержит Sun
[1] 7
  • str_count() позволяет подсчитать число обнаруженных совпадений в строке.
  • str_remove() и str_remove_all() удаляют символы из строки по шаблону.
  • str_replace() и str_replace_all() заменяют символы в строке по шаблону.
  • str_extract() и str_extract_all() возвращают найденное слово/шаблон в каждой строке.
  • str_subset() возвращает строки, содержащие слово/шаблон.

Функции str_remove() и str_remove_all() (и подобные им) различаются тем, что либо работают только с первым совпадением в строке, либо работают со всеми совпадениями.

Регулярные выражения

Перечисленные выше функции для поиска слов в строке работают и с регулярными выражениями. Подробнее про то, как составлять регулярные выражения в R, можно посмотреть в cheat sheet по пакету {stringr}.

Например, символы ^ и $ задают начало и конец строки, соответственно.

str_detect(weekdays,"^S") # начинается на S
[1] FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE
str_count(weekdays, "[aeiou]") # подсчитать все гласные
[1] 2 3 3 2 2 3 2

При работе со специальными символами нужно их экранировать.

str_count(c("what?", "when??", "how?!!"), "?")
Error in stri_count_regex(string, pattern, opts_regex = opts(pattern)): Syntax error in regex pattern. (U_REGEX_RULE_SYNTAX, context=`?`)
str_count(c("what?", "when??", "how?!!"), "\\?")
[1] 1 2 1

Кроме того, функционал {stringr} позволяет визуализировать регулярные выражения в вашем датасете с помощью функции str_view_all().

str_view_all(weekdays, "[aeiou]")
[1] │ M<o>nd<a>y
[2] │ T<u><e>sd<a>y
[3] │ W<e>dn<e>sd<a>y
[4] │ Th<u>rsd<a>y
[5] │ Fr<i>d<a>y
[6] │ S<a>t<u>rd<a>y
[7] │ S<u>nd<a>y

Разбиение строки по разделителю

Функция str_split() позволяет разбить строку на несколько по указанному разделителю или шаблону. Результат выдается в виде списка.

starwars %>% 
  head() %>% 
  mutate(
    hair_color_splitted = str_split(hair_color, ", ")) %>% 
  pull(hair_color_splitted)
[[1]]
[1] "blond"

[[2]]
[1] NA

[[3]]
[1] NA

[[4]]
[1] "none"

[[5]]
[1] "brown"

[[6]]
[1] "brown" "grey" 

Преобразование строки в параграф

Функция str_wrap() позволяет заменять некоторые пробелы с строках из нескольких слов на символы переноса строки \n. Эта функция может пригодиться при добавлении на график длинного текста, который в виде единой строки не поместился бы в границы графика.

str_wrap("Курс для студентов ФББ 'Язык R и его применение в биоинформатике'", width = 20)
[1] "Курс для студентов\nФББ 'Язык R и\nего применение в\nбиоинформатике'"

Полезные ссылки

Задания

Задание 1

Возьмите встроенный набор данных - fruit.

  1. Удалите из названий фруктов все гласные буквы (aeiou). Используйте функции str_remove() и str_remove_all(). Сравните результаты.
  2. Найдите все названия фруктов, которые содержат слово berry.

Задание 2

В ходе некоторого анализа был получен список (вектор) из очень важных функциональных категорий генов - они закодированы с помощью идентификаторов. Однако в векторе оказались смешаны идентификаторы из разных баз данных - Gene Ontology (начинаются на GO:) и KEGG (начинаются на hsa в случае человеческих генов).

gene_cat <- c("GO:1902222", "hsa00380", "hsa00630", "GO:0006559", "GO:0042773", "hsa00350", "hsa00730", "GO:0051792", "GO:0006572", "GO:0006573", "GO:0032324", "GO:0006390", "GO:0009250", "hsa01212", "GO:0005978")
  1. Разделите этот вектор на два в соотвествии с двумя типами идентификаторов из разных баз данных.
  2. У всех этих идентификаторов значимыми являются только несколько последних цифр, которые идут после 0, поэтому извлеките только их.

Задание 3

Из абстрактов молекулярно-биологических статей можно понять, о каких генах преимущественно идет речь в статье. Для каждого из абстрактов вычлените названия генов, которые в них упоминаются. Названия генов, которые мы ищем, содержат все заглавные буквы и цифры и длиной не короче 3 символов.

abstracts <- c(
  "Atherosclerosis (AS) is one of the main causes of cardiovascular diseases (CVDs). Trimethylamine N-oxide (TMAO) exacerbates the development of AS. This study aimed to investigate the roles of TMAO in AS. In this study, mice were fed with high fat food (HF) and/or injected with TMAO. Oil red O staining was applied for histological analysis. ELISA, qRT-PCR, and western blot were conducted to determine the TMAO, serum, mRNA, and protein levels. CCK-8, colony formation assay, and flow cytometry assays were performed to detect the functions of human aortic endothelial cells (HUVECs). The results showed that TMAO induced thick internal and external walls and intimal plaques in vivo, and HUVECs dysfunction in vitro. TMAO and lncRNA enriched abundant transcript 1 (NEAT1) were increased in AS clinical samples and TMAO-HUVECs. Downregulated NEAT1 inhibited proliferation and promoted the apoptosis of HUVECs. NEAT1 regulated the expression of signal transducer and activator of transcription 3 (STAT3) via sponging miR-370-3p. Overexpression of miR-370-3p facilitated the effects of NEAT1 on the cellular functions of HUVECs, while STAT3 exerted opposing effects. The activation of STAT3 promoted the expression of flavin-containing monooxygenase-3 (FMO3). Taken together, our results show that TMAO-NEAT1/miR-370-3p/STAT3/FMO3 forms a positive feedback loop to exacerbate the development of AS. This novel feedback loop may be a promising therapeutic target for AS.",
  "RNA G-quadruplexes (rG4s) have functional roles in many cellular processes in diverse organisms. While a number of rG4 examples have been reported in coding messenger RNAs (mRNA), so far only limited works have studied rG4s in non-coding RNAs (ncRNAs), especially in long non-coding RNAs (lncRNAs) that are of emerging interest and significance in biology. Herein, we report that MALAT1 lncRNA contains conserved rG4 motifs, forming thermostable rG4 structures with parallel topology. We also show that rG4s in MALAT1 lncRNA can interact with NONO protein with high specificity and affinity in vitro and in nuclear cell lysate, and we provide cellular data to support that NONO protein recognizes MALAT1 lncRNA via rG4 motifs. Notably, we demonstrate that rG4s in MALAT1 lncRNA can be targeted by the rG4-specific small molecule, peptide, and L-aptamer, leading to the dissociation of MALAT1 rG4-NONO protein interaction. Altogether, this study uncovers new and important rG4s in MALAT1 lncRNAs, reveals their specific interactions with NONO protein, offers multiple strategies for targeting MALAT1 and its RNA-protein complex via its rG4 structure and illustrates the prevalence and significance of rG4s in ncRNAs.",
  "Automated and accurate EGFR mutation status prediction using computed tomography (CT) imagery is of great value for tailoring optimal treatments to non-small cell lung cancer (NSCLC) patients. However, existing deep learning based methods usually adopt a single task learning strategy to design and train EGFR mutation status prediction models with limited training data, which may be insufficient to learn distinguishable representations for promoting prediction performance. In this paper, a novel multi-task learning method named AIR-Net is proposed to precisely predict EGFR mutation status on CT images. First, an auxiliary image reconstruction task is effectively integrated with EGFR mutation status prediction, aiming at providing extra supervision at the training phase. Particularly, we adequately employ multi-level information in a shared encoder to generate more comprehensive representations of tumors. Second, a powerful feature consistency loss is further introduced to constrain semantic consistency of original and reconstructed images, which contributes to enhanced image reconstruction and offers more effective regularization to AIR-Net during training. Performance analysis of AIR-Net indicates that auxiliary image reconstruction plays an essential role in identifying EGFR mutation status. Furthermore, extensive experimental results demonstrate that our method achieves favorable performance against other competitive prediction methods. All the results executed in this study suggest that the effectiveness and superiority of AIR-Net in precisely predicting EGFR mutation status of NSCLC.",
  "Driver mutations promote initiation and progression of cancer. Pharmacological treatment can inhibit the action of the mutant protein; however, drug resistance almost invariably emerges. Multiple studies revealed that cancer drug resistance is based upon a plethora of distinct mechanisms. Drug resistance mutations can occur in the same protein or in different proteins; as well as in the same pathway or in parallel pathways, bypassing the intercepted signaling. The dilemma that the clinical oncologist is facing is that not all the genomic alterations as well as alterations in the tumor microenvironment that facilitate cancer cell proliferation are known, and neither are the alterations that are likely to promote metastasis. For example, the common KRasG12C driver mutation emerges in different cancers. Most occur in NSCLC, but some occur, albeit to a lower extent, in colorectal cancer and pancreatic ductal carcinoma. The responses to KRasG12C inhibitors are variable and fall into three categories, (i) new point mutations in KRas, or multiple copies of KRAS G12C which lead to higher expression level of the mutant protein; (ii) mutations in genes other than KRAS; (iii) original cancer transitioning to other cancer(s). Resistance to adagrasib, an experimental antitumor agent exerting its cytotoxic effect as a covalent inhibitor of the G12C KRas, indicated that half of the cases present multiple KRas mutations as well as allele amplification. Redundant or parallel pathways included MET amplification; emerging driver mutations in NRAS, BRAF, MAP2K1, and RET; gene fusion events in ALK, RET, BRAF, RAF1, and FGFR3; and loss-of-function mutations in NF1 and PTEN tumor suppressors. In the current review we discuss the molecular mechanisms underlying drug resistance while focusing on those emerging to common targeted cancer drivers. We also address questions of why cancers with a common driver mutation are unlikely to evolve a common drug resistance mechanism, and whether one can predict the likely mechanisms that the tumor cell may develop. These vastly important and tantalizing questions in drug discovery, and broadly in precision medicine, are the focus of our present review. We end with our perspective, which calls for target combinations to be selected and prioritized with the help of the emerging massive compute power which enables artificial intelligence, and the increased gathering of data to overcome its insatiable needs."
)

Задание 4

Прочитайте датасет с репликами героев первых пяти серий первого сезона “Ведьмака”, датасет доступен по ссылке https://raw.githubusercontent.com/kirushka/datasets/main/witcher.csv. Ссылку можно использовать как путь до файла при чтении датасета в R.

Посмотрите и изучите как он выглядит и что содержит.

witcher <- read_csv("https://raw.githubusercontent.com/kirushka/datasets/main/witcher.csv")

glimpse(witcher)
Rows: 1,478
Columns: 2
$ Character <chr> "Isadora", "Geralt", "Isadora", "Inkeeper", "Geralt", "Nohor…
$ Text      <chr> "What will it be?", "Point me to the alderman's house.", "It…
  1. Посчитайте, какой процент реплик Геральта начинается с его знаменитого “Хм” (по-английски “Hm”).
  2. В скольких репликах Геральт обращается к Плотве (“Roach”)?

Графика с {ggplot2}

В ggplot-графике используется особый синтаксис (the layered grammar of graphics): элементы, определяющие график, добавляются на рисунок послойно. Слои графика, определяемые функциями {ggplot2} (и из совместимых пакетов), соединяются в единый объект с помощью знаков сложения +.

# ОБЯЗАТЕЛЬНОЕ
ggplot(
  data = <DATA>,               # данные
  mapping = aes(<MAPPINGS>)) + # переменные по осям X, Y, цвет...
  <GEOM_FUNCTION>() +          # тип графика
  
# ДОПОЛНИТЕЛЬНОЕ  
  <SCALE_FUNCTION>() +         # трансформация осей
  <COORDINATE_FUNCTION>() +    # настройка системы координат
  <FACET_FUNCTION>() +         # разделение графика на панель
  <THEME_FUNCTION>()           # настройка оформления графика

Вариативность записи кода

Последовательность использования ggplot2-функций при создании графика обычно не важна, но может играть роль при создании сложных визуализаций, например, комбинирующих несколько типов графиков. Тем не менее, создание графика всегда начинается с функции ggplot(), которая “создает холст”, на который будут добавляться элементы графика.

При вызове функции ggplot() удобно сразу указать датафрейм - источник данных, которые мы визуализируем, и задать графические переменные (“что по осям?”) с помощью функции aes(). В таком случае все функции, используемые для построения вашего графика, будут обращаться к указанному источнику данных и заданным графическим переменным. Однако у геометрических функций есть свои параметры data = и mapping =, поэтому один и тот же график можно создать с помощью немного отличающегося кода или при создании сложного графика отдельно настроить работу разных слоев графика.

Стоит отметить, что {ggplot2} также отлично сочетается с конвейерным подходом.

Например, показанный ниже график плотности можно создать, записав код немного по-разному:

ggplot(starwars, aes(x = height)) +
  geom_density(fill = "yellowgreen")

# используя конвейер
starwars %>% 
  ggplot(aes(x = height)) +
  geom_density(fill = "yellowgreen")

# указав aes отдельно для geom_point
starwars %>% 
  ggplot() +
  geom_density(aes(x = height), fill = "yellowgreen")

# указав data и aes отдельно для geom_point
ggplot() +
  geom_density(aes(x = height), data = starwars, fill = "yellowgreen")

Комбинирование geom’ов

Создавая график, можно использовать несколько геометрических функций (geom_), чтобы комбинировать типы графиков. В таком случае порядок записи геометрических функций может оказаться важен, поскольку добавляемые geom’ы, будут отрисовываться поверх предыдущих.

starwars %>%
  filter(homeworld %in% c("Naboo", "Tatooine")) %>%
  ggplot(aes(x = homeworld, y = height, fill = homeworld)) +
  geom_violin(alpha = 0.6) +
  geom_boxplot(width = 0.4) +
  geom_jitter(width = 0.05) +
  scale_fill_manual(values = c("skyblue", "khaki"))
1
Отбираем из датафрейма starwars только персонажей с планет Набу и Татуин
2
Откладываем по оси X родные планеты, по Y - рост персонажей, дублируем обозначение планет с помощью цвета (заливки)
3
Визуализируем распределения роста с помощью скрипичной диаграммы
4
Добавляем поверх скрипичных диаграмм бокплоты
5
Добавляем точки (geom_jitter - аналог geom_point, но рисует точки с некоторым разбросом)
6
Вручную задаем цветовую палитру

Графические переменные

Геометрические функции отличаются наборами графических переменных, посредством которых можно закодировать значения признаков из вашего датасета. В первую очередь вы будете использовать x и/или y, чтобы отложить выбранные признаки по осями. Также для большинства отрисовываемых геометрических объектов можно задать цвет с помощью color (задать константный цвет или задать соответствие между значением и цветом в палитре). Некоторые геометрические объекты (например, столбцы гистограммы или столбчатой диаграммы) обладают как внутренней заливкой, так и внешней обводкой. В таком случае для заливки используется fill, для обводки color.

starwars %>%
  filter(homeworld %in% c("Naboo", "Tatooine")) %>%
  ggplot(aes(x = mass, fill = homeworld)) +
  geom_density(alpha = 0.6, color = "yellowgreen")
1
Отбираем из датафрейма starwars только персонажей с планет Набу и Татуин
2
Откладываем по оси X вес персонажа, с помощью цвета (заливка - fill) кодируем родную планету
3
Визуализируем распределения роста с помощью графика плотности, задаем прозрачность (alpha) и меняем цвет (обводка - color) границы графиков

Управление графическими переменными

То, как у вас отображаются оси X, Y, как задаются цветовые шкалы и отображаются другие используемые на графике графические переменные, настраивается с помощью функций вида scale_x_, scale_y_, scale_color_, scale_fill_ (в общем виде scale_{aes}_). Выбирая нужную scale_ функцию, важно понимать, работаете ли вы с количественными или категориальными признаками, хотите ли вы задавать цветовую палитру вручную, использовать готовую или создавать градиент и т.д.

Важными параметрами этих функций являются breaks и labels. Через breaks можно подать вектор со значениями, которые будут отображаться по осям (через них будут проходить основные линии сетки) или в легенде. В свою очередь параметр labels помогает изменить то, как эти значения будут подписаны.

starwars %>%
  ggplot(aes(x = height)) +
  geom_density(fill = "yellowgreen") +
  scale_x_continuous(
    name = "Height in meters",
    breaks = seq(80, 240, 40),
    labels = seq(0.8, 2.4, 0.4))
1
Используя датафрейм starwars, строим график плотности роста персонажей ЗВ
2
Настраиваем отображение оси X, по которой отложен непрерывный (continuous) количественный признак
3
Задаем название оси
4
Задаем вектор значений, которые будут показаны по оси
5
Задаем вектор с подписями

Пакет {scales} содержит много полезных функций для отображения подписей по осям.

starwars %>%
  ggplot(aes(x = height)) +
  geom_density(fill = "yellowgreen") +
  scale_x_continuous(
    name = "Height",
    breaks = seq(80, 240, 40),
    labels = scales::label_number(scale = 0.01, suffix = " m"))
1
Используя датафрейм starwars, строим график плотности роста персонажей ЗВ
2
Настраиваем отображение оси X, по которой отложен непрерывный (continuous) количественный признак
3
Задаем название оси
4
Задаем вектор значений, которые будут показаны по оси
5
Используем функцию из пакета {scales}, чтобы модифицировать отображаемые по оси значения

Если по оси X/Y отложены количественные признаки, то используются функции scale_x_continuous()/scale_y_continuous(), если категориальные - scale_x_discrete()/scale_y_discrete().

Функции scale_x_log10() и scale_y_log10() позволяют логарифмировать X и Y оси. Данная трансформация пригождается, когда у вас есть несколько наблюдений с высокими значениями признака, но основная масса наблюдений кучкуется ближе к 0.

starwars %>% 
  ggplot(aes(x = mass)) +
  geom_histogram(fill = "yellowgreen") 

starwars %>% 
  ggplot(aes(x = mass)) +
  geom_histogram(fill = "yellowgreen") +
  scale_x_log10()

Работа с цветом

Когда вы задаете цветовую графическую переменную (color или fill), то значениям этой переменной присваиваются цвета из стандартных палитр {ggplot2} - набор дискретных цветов для обозначения категориальных признаков и градиент для обозначения количественных признаков. Если вам не подходят стандартные цвета, то есть два варианта: вы используете другие готовые палитры и градиенты или создаете цветовую шкалу самостоятельно.

Из готовых палитр наиболее популярными являются палитры из пакетов {viridis} (нужно установить) и {RColorBrewer} (устанавливается вместе с {tidyverse}). Эти пакеты предоставляют несколько вариантов палитр, подходящих для визуализации как непрерывных количественных признаков, так и дискретных или категориальных признаков. Чтобы использовать в графике палитры из данных пакетов, нужно воспользоваться функциями scale_color_viridis() или scale_color_brewer() (или их версиями для fill). Также для использования палитр viridis можно воспользоваться функциями scale_color_viridis_c() (градиентная шкала), scale_color_viridis_d() (дискретная цветовая палитра) или scale_color_viridis_b() (градиент разбивается на бины) из пакета {ggplot2}.

starwars %>%
  filter(homeworld %in% c("Naboo", "Tatooine")) %>%
  ggplot(aes(x = mass, fill = homeworld)) +
  geom_density(alpha = 0.6, color = "yellowgreen") +
  scale_fill_brewer(palette = "Accent")
1
Отбираем из датафрейма starwars только персонажей с планет Набу и Татуин
2
Отрисовываем распреление веса персонажей с двух разных планет с помощью графика плотности
3
Используем палитру ‘Accent’ из пакета {RColorBrewer}

Помимо названных выше двух пакетов существуют многие другие, предоставляющие различные цветовые палитры: {ggsci}, {ggthemes}, {wesanderson} и т.д.

В случае работы с категориальным признаком цветовую схему вручную можно задать с помощью функций scale_color_manual() или scale_fill_manual(). Если же вы изображаете с помощью цвета непрерывную количествуенную переменную, то стоит использовать градиент цвета. Градиент можно выстроить как переход между двумя цветами, которые будут соответствовать наименьшему (low) и наибольшему (high) значениям переменной. Если количественный признак предусматривает “срединное” значение (например, ноль, разделяющий положительные и отрицательные значения), то стоит указать дополнительную точку (mid), относительно которой будет строиться дивергентная цветовая палитра. Также можно строить градиент, проходящий через произвольное число цветов. Для этих трех разных ситауация используются три разные функции: scale_color_gradient(), scale_color_gradient2() и scale_color_gradientn(). Аналогичные функции есть и для графической переменной fill.

starwars %>%
  filter(species %in% c("Droid", "Gungan")) %>%
  ggplot(aes(x = species, y = height, color = mass)) +
  geom_point(size = 5, alpha = 0.8) +
  scale_color_gradient(
    low = "#455e89", high = "#b7094c",
    breaks = seq(50, 150, 50),
    limits = c(30, 150))
1
Отбираем из датафрейма starwars только дроидов и гунганов
2
Строим точковую диаграмму (dotplot), показывающую рост и вес для двух рас
3
Указываем градиент, построенный по двум цветам

Несколько легенд

Для каждой дополнительной графической переменной (color, fill, shape, size и т.д.), которую вы используте для создания своего графика, появляется собственная легенда. Функция guides() предоставляет дополнительные опции для настройки отображения легенд. “Обычные” легенды, имеющие дискретные элементы, настраиваются с помощью функции guide_legend(), непрерывные цветовые шкалы - с помощью guide_colorbar().

starwars %>%
  filter(species %in% c("Droid", "Gungan")) %>%
  ggplot(aes(x = species, y = height, color = mass, size = mass)) +
  geom_point(alpha = 0.8) +
  scale_color_gradient(low = "#455e89", high = "#b7094c") +
  scale_size_continuous(breaks = seq(40, 140, 40)) +
  guides(
    color = guide_colorbar(order = 1, title = "Body mass (kg)"),
    size = guide_legend(order = 2, reverse = TRUE, title = ""))
1
Отбираем из датафрейма starwars только дроидов и гунганов
2
Строим точковую диаграмму (dotplot), показывающую рост и вес для двух рас
3
Указываем градиент, построенный по двум цветам
4
Настраиваем отображение легенды для размера точек
5
Фиксируем положение легенд относительно друг друга (order), задаем названия (title), настраиваем порядок элементов (reverse) в легенде, объясняющей размер точек

Кроме того, с помощью функции guides() можно удалить одну из легенд: guides(size = "none").

Добавление линий на график

Для добавления на график горизонтальных, вертикальных линий или линий с любым наклоном исаользуются функции geom_hline(), geom_vline() и geom_abline().

starwars %>% 
  ggplot(aes(x = height, y = mass)) +
  geom_point(size = 3, alpha = 0.8, color = "coral") +
  scale_y_log10() +
  geom_vline(xintercept = 164, linetype = "dashed", color = "firebrick", linewidth = 1) +
  coord_cartesian(xlim = c(0, 300))

Добавление подписей на график

Произвольный текст можно добавить на график с помощью функции annotate().

starwars %>%
  filter(species %in% c("Droid", "Gungan")) %>%
  ggplot(aes(x = species, y = height)) +
  geom_point(size = 5, color = "#b7094c", alpha = 0.5) +
  annotate(
    "text", x = 1.5, y = 200,
    label = str_wrap("Редкий дроид достигает роста гунгана", 20))
1
Отбираем из датафрейма starwars только дроидов и гунганов
2
Строим точковую диаграмму (dotplot), показывающую рост для двух рас
3
Добавляем текст на график: в качестве geom’а указываем “text”, задаем координаты (x = 1.5 означает между первой и второй категорией по X) и сам текст

Если же вы хотите добавить на график текстовые подписи, которые будут привязаны к определенным координатам и отрисовываемым геометрическим объектам, то следует использовать функции geom_text() или geom_label(). Вторая функция отличается от первой наличием рамки вокруг текста. У этих функций есть собственная графическая переменная label, через которую можно задать столбец, из которого брать текст для подписей.

starwars %>%
  filter(species %in% c("Droid", "Gungan")) %>%
  ggplot(aes(x = species, y = height)) +
  geom_point(size = 5, color = "#b7094c", alpha = 0.5) +
  geom_text(aes(label = name), nudge_x = 0.2)
1
Отбираем из датафрейма starwars только дроидов и гунганов
2
Строим точковую диаграмму (dotplot), показывающую рост для двух рас
3
Добавляем имена персонажей в виде подписей рядом с точками (nudge_x использутся для сдвига по горизонтали)

Однако, как видно на примере графика выше, в некоторых случаях подписи будут накладываться друг на друга, что значительно затруднит восприятие информации. В такой ситуации удобно использовать функции geom_text_repel() и geom_label_repel() из пакета {ggrepel} (необходимо установить), которые минимизируют пересечения между подписями, располагая их в некотром случайном отдалении от заданных x,y координат.

library(ggrepel)

starwars %>%
  filter(species %in% c("Droid", "Gungan")) %>%
  ggplot(aes(x = species, y = height)) +
  geom_point(size = 5, color = "#b7094c", alpha = 0.5) +
  geom_text_repel(aes(label = name))
1
Подгружаем пакет {ggrepel} (перед этим установили его: install.packages("ggrepel"))
2
Отбираем из датафрейма starwars только дроидов и гунганов
3
Строим точковую диаграмму (dotplot), показывающую рост для двух рас
4
Добавляем имена персонажей в виде подписей рядом с точками

Дизайн графика

В ggplot-графиках по умолчанию используется серая тема (theme_grey()), которая задает вид всех элементов графика, которые не зависят от подаваемых на вход данных (фон графика, сетка, линии осей, размер, шрифт и положений подписей по осям и т.д.). В качестве альтернативы стандартной серой теме можно выбрать другие готовые (начните набирать theme_, и появится их список) или изменить отображение любого элемента графика самостоятельно с помощью функции theme(). Для настройки элементов графика используются три основные функции: element_text() для текстовых элементов, element_line() для всех элементов в виде линий и element_rect() для фонов и границ отдельных областей графика.

Ниже приведены некоторые параметры функции theme(), которые вам могут пригодиться в первую очередь:

  • aspect.ratio = 1 - соотношение сторон графика 1:1
  • axis.text = element_text(color = "black", size = 12) - цвет подписей по X и Y осям черный, размер текста - 12 (увеличен по сравнению со стандартным)
  • axis.text.x = element_text(angle = 45, hjust = 1) - подписи по оси X под углом 45°, выравнивание по горизонтали по правому краю
  • legend.position = "top" - легенда над графиком
  • legend.position = "none" - нет легенды

Шрифты

Менять шрифты на графике может оказаться достаточно сложной задачей…

Для работы со шрифтами в R существует несколько пакетов: {showtext}, {extrafont}, {systemfonts} и другие (нужно устанавливать). Ниже приведен пример изменения шрифтов на графике с помощью пакета {showtext}. Он позволяет подгружать и использовать шрифты с сайта Google Fonts. Для того, чтобы шрифты корректно отображались в html-отчетах, генерируемых из .Rmd файлов, необходимо указать среди опций блока кода fig.showtext=TRUE.

library(showtext)

font_add_google("Oswald", "oswald")
font_add_google("Press Start 2P", "press_start")

showtext_auto()

starwars %>%
  filter(species %in% c("Droid", "Gungan")) %>%
  ggplot(aes(x = species, y = height)) +
  geom_point(size = 5, color = "#b7094c", alpha = 0.5) +
  geom_text_repel(aes(label = name), family = "press_start", )  +
  theme(text =  element_text(family = "oswald"))
1
Подгружаем пакет {showtext} (перед этим установили его: install.packages("showtext"))
2
Подгружаем два шрифта из Google Fonts
3
Включаем автоматическое использование showtext во всех графических девайсах
4
Отбираем из датафрейма starwars только дроидов и гунганов
5
Строим точковую диаграмму (dotplot), показывающую рост для двух рас
6
Добавляем имена персонажей в виде подписей рядом с точками, указываем шрифт для подписей (family)
7
Задаем шрифт для всех текстовых элементов графика

Полезные ссылки

Задания

Потренируйтесь создавать и сохранять графики. Готовые графики показаны для ориентира, не нужно пытаться их воспроизвести до мелочей.

Задание 1

Возьмите встроенный датасет starwars - в нем содержится информация о персонажах вселенной Звездные Войны. Больше информации об этом датасете можно узнать в справке ?starwars.

Отберите 2 планеты (homeworld), которые являются родиной самого большого количества героев ЗВ. Отберите только тех персонажей, которые происходят с этих двух планет, и постройте график дотплот (с помощью функции geom_point()), который бы показывал вес (mass) персонажей разных рас (species). По оси X - вес тела, по Y - раса (species), каждая точка - один персонаж. Цветом точки покажите гендерную идентичность героя (gender) информацию о расе, размером точки - его рост (height).

Подпишите оси, добавьте название графика и подберите цветовую палитру.

Сохраните график в подходящем размере и удобном вам формате.

Задание 2

Прочитайте датасет о напитках из Старбакса по ссылке https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-12-21/starbucks.csv.

В этом датасете содержатся столбцы:

  • product_name - наименование напитка,
  • size - размер (категория),
  • milk - тип молока:
    • 0 - без молока,
    • 1 - обезжиренное молоко,
    • 2 - 2% молоко,
    • 3 - соевое молоко,
    • 4 - кокосовое молоко,
    • 5 - цельное молоко,
  • whip - добавляют ли сливки (0/1),
  • serv_size_m_l - объем напитка (мл),
  • calories - калории (ккал),
  • total_fat_g - содержание жира (г),
  • saturated_fat_g - содержание насыщенных жиров (г),
  • trans_fat_g - содержание транс-жиров (г),
  • cholesterol_mg - содержание холестерина (мг),
  • sodium_mg - содержание натрия (мг),
  • total_carbs_g - содержание углеводов (г),
  • fiber_g- содержание пищевых волокон (г),
  • sugar_g - содержание сахара (г),
  • caffeine_mg - содержание кофеина (мг).

Отберите только напитки, подходящие под следующие условия:

  • напитки, приготовляемые без молока, 2% молоке или соевом молоке,
  • напитки объемом 473 мл,
  • не бескалорийные напитки,
  • напитки, содержащие кофеин.

С помощью диаграммы рассеяния изобразите зависимость содержание кофеина (caffeine_mg) от калорийности напитка (calories). Цветом обозначьте тип молока.

На графике обозначьте пунктирной линией (используйте geom_hline(..., linetype = "dashed"), например) самое частое (мода) для отобранных напитков значение содержания кофеина. Поменяйте порядок задаваемых геометрических объектов (geom_*), чтобы линия проходила под точками.

Поменяйте отображаемые по осям значения так, чтобы интервал между ними составлял 50. Это можно сделать с помощью scale_x_continuous(breaks = *вектор с отображаемыми значениями*) и scale_y_continuous(breaks = *вектор с отображаемыми значениями*).

Пусть в легенде будут перечислены категории напитков следующим образом:

  • напитки без молока - no milk
  • напитки на 2% молоке - 2% milk
  • напитки на соевом молоке - soy milk

Подпишите оси, добавьте название графика и подберите цветовую палитру.

Сохраните график в подходящем размере и удобном вам формате.

Задание 3

Использйуте датасет про напитки из Старбакса из задания 3.

На одном графике постройте гитограмму и плотность распределения содержания сахара во всех напитках. geom_histogram и geom_density преобразовывают ваши данные и отрисовывают либо каунты, либо плотность. Найдите способ, чтобы оба geom_ отрисовывали значения по оси Y согласованно.

Подпишите оси, добавьте название графика. Подберите цветовую палитру.

Сохраните график в подходящем размере и удобном вам формате.

Задание 4

Прочитайте датасет о рейтинге различных эпизодов сериала “Могучие рейнджеры” по ссылке https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2024/2024-08-27/power_rangers_episodes.csv.

В этом датасете содержатся столбцы:

  • season_title - название сезона,
  • episode_num - номер эпизода,
  • episode_title - название эпизода,
  • air_date - дата выхода эпизода,
  • IMDB_rating - средний рейтинг эпизода на IMDB,
  • total_votes - общее число голосов на IMDB,
  • desc - описание эпизода.

Визуализируйте распределение рейтинга эпизодов из разных сезонов. С помощью точек покажите рейтинг индивидуальных эпизодов, а также с помощью цветовой шкалы добавьте информацию об общем количестве голосов за каждый эпизод.

Подпишите оси, добавьте название графика. Подберите цветовую палитру.

Сохраните график в подходящем размере и удобном вам формате.

Задание 5

Загрузите датасет, содержащий информацию про цветение сакуры в Японии за 1953-2019 года. https://raw.githubusercontent.com/tacookson/data/master/sakura-flowering/sakura-modern.csv.

Изучите датасет! Про него можно прочитать дополнительно, например, здесь: https://github.com/tacookson/data/blob/master/sakura-flowering/README.md.

Информация про датасет:

  • station_id - ID метеостанции (города),
  • station_name - название города, где эта метеостанция расположена,
  • latitude, longitude - широта и долгота метеостанции,
  • year - год,
  • flower_date - дата начала цветения сакуры,
  • flower_doy - день с начала года, когда началось цветение сакуры,
  • full_bloom_date - дата полного цвета сакуры,
  • full_bloom_doy - день с начала года, на который пришелся полный цвет сакуры.

Визуализируйте, как шел фронт цветения сакуры в Японии в разные годы, с помощью линейного графика - используйте geom_line. По горизонтали отложите года, по вертикали - дату или день начала цветения/полного цвета. Каждая кривая - это один город. Не забудьте сообщить, что вы решили визуализировать (какие переменные), в названиях осей и в названии графика.

Сохраните график в подходящем размере и удобном вам формате.

Примечания:

  1. Кривая - это набор точек, соединенных линиями. Поэтому чтобы точки правильно соединились в кривые по городам, укажите aesthetic group = station_name.
  2. Если вам мешают отсутствующие значения данных, избавьтесь от них.
  3. Чтобы сделать график интереснее, подсветите кривую одного из городов, какой вам больше интересен, например, Kyoto. Сделайте так, чтобы кривая этого города была ярче, чем остальные кривые. Это можно сделать, подобрав цвета или прозрачность. Или и то, и другое :)

Есть несколько способов, как можно “подсветить” одну линию. Предлагаю воспользоваться одним из них или придумать свой. Вариант 1. Разделите датасет на 2: с выбранным городом и с остальными городами. В графике используйте geom_line дважды с этими двумя новыми датасетами (data = ...). Для каждого geom_line укажите свой цвет/прозрачность/что-то еще.

Вариант 2. Создайте новый столбец, где будут 2 значения: ваш город и остальные города. Используйте этот столбец, чтобы задать 2 цвета. Иногда бывает удобно создавать столбец сразу со значениями цветов/уровней прозрачности и др. и напрямую использовать их в качестве aesthetic.

Вариант 3. Поищите R пакеты, которые помогают легко решить эту задачу. Например, есть пакет {gghighlight} (он не входит в {tidyverse}, его нужно устанавливать отдельно).