Язык R

и его применение в биоинформатике

Лекция 4

Анна Валяева

22 сентября 2023

Типы данных

Количественные признаки

Типы данных

Категориальные признаки

Пример - данные про пингвинов

Данные из пакета palmerpenguins.

Artwork by @allison_horst

Пример - данные про пингвинов

penguins <- read_csv("data/penguins.csv")
penguins
# A tibble: 344 × 8
   species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
   <chr>   <chr>              <dbl>         <dbl>             <dbl>       <dbl>
 1 Adelie  Torgersen           39.1          18.7               181        3750
 2 Adelie  Torgersen           39.5          17.4               186        3800
 3 Adelie  Torgersen           40.3          18                 195        3250
 4 Adelie  Torgersen           NA            NA                  NA          NA
 5 Adelie  Torgersen           36.7          19.3               193        3450
 6 Adelie  Torgersen           39.3          20.6               190        3650
 7 Adelie  Torgersen           38.9          17.8               181        3625
 8 Adelie  Torgersen           39.2          19.6               195        4675
 9 Adelie  Torgersen           34.1          18.1               193        3475
10 Adelie  Torgersen           42            20.2               190        4250
# ℹ 334 more rows
# ℹ 2 more variables: sex <chr>, year <dbl>

Типы графиков

Категориальные признаки

  • Распределение наблюдений по категориям
    • Число пингвинов разных видов
    • Число самок и самцов среди пингвинов разных видов

Столбчатая диаграмма

Количественные признаки

  • Распределение одного количественного признака
    • Разброс длин крыльев пингвинов
  • Распределение одного количественного признака в разных категориях
    • Разброс длин крыльев у разных видов пингвинов

Гистограмма и график плотности

Количественные признаки

  • Распределение одного количественного признака в разных категориях
    • Разброс длин крыльев у разных видов пингвинов
    • Разброс длин крыльев у самок и самцов разных видов пингвинов

Диаграмма размаха

Количественные признаки

  • Взаимосвязь двух количественных признаков
    • Связь длины и ширины клюва у пингвинов
    • Соотношение длины крыла и массы тела пингвинов разных видов

Диаграмма разброса

Типы графиков 🏠

  • Один или несколько категориальных признаков
    • Столбчатая диаграмма
    • Круговая диаграмма
    • Диаграмма в виде плоского дерева [treemap]
    • Диаграмма Венна
    • Диаграмма UpSet
    • Потоковая диаграмма [Sankey diagram]

Как выбрать график под ваши данные

Типы графиков 🏠

  • Один количественный признак
    • Гистограмма
    • График плотности
  • Один количетвенный и один или несколько категориальных признаков
    • Диаграмма размаха
    • Скрипичная диаграмма [Violin plot]
    • Ridgeline график
  • Два или несколько количественных признаков
    • Диаграмма разброса
    • Линейная диаграмма

Как выбрать график под ваши данные

ggplot2 графика

ggplot2

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


Данные -> …

  • создается пустой “холст” для графика
ggplot(data = penguins)

Данные -> оси -> …

  • появляются обозначения переменных по осям X и Y
ggplot(data = penguins, 
       mapping = aes(
         x = bill_length_mm, 
         y = bill_depth_mm))

Данные -> оси -> тип графика -> …

  • появляются точки - обозначения индивидуальных наблюдений из набора данных
ggplot(data = penguins, 
       mapping = aes(
         x = bill_length_mm, 
         y = bill_depth_mm)) +
  geom_point(size = 3, alpha = 0.8)

Данные -> оси -> тип графика -> тема -> …

  • меняется оформление графика - черно-белая тема вместо серой
ggplot(data = penguins, 
       mapping = aes(
         x = bill_length_mm, 
         y = bill_depth_mm)) +
  geom_point(size = 3, alpha = 0.8) +
  theme_bw()

Оформление графика

В ggplot2 есть несколько встроенных тем для оформления графика:

  • theme_grey() - стандартная серая тема
  • theme_bw()
  • theme_classic()
  • theme_void()

Добавим цвет - еще один параметр в aes

  • добавляется обозначение разных категорий наблюдений с помощью цвета
  • используется стандартная палитра для дискретных признаков
ggplot(data = penguins, 
       mapping = aes(
         x = bill_length_mm, 
         y = bill_depth_mm,
         color = species)) +
  geom_point(size = 3, alpha = 0.8) +
  theme_bw()

Задать набор цветов

  • вручную задать цветовую палитру можно с помощью функции scale_color_manual()
ggplot(data = penguins, 
       mapping = aes(
         x = bill_length_mm, 
         y = bill_depth_mm,
         color = species)) +
  geom_point(size = 3, alpha = 0.8) + 
  scale_color_manual(
    values = c("#E2856E", "#F2B969", "#7C99A2")) +
  theme_bw()

Цветовая палитра 🏠

Цвета можно задать с помощью:

  • наименования цвета: “blue”, “red”, “purple”, …
    • все доступные в R цвета можно узнать с помощью функции color()
  • номер цвета из палитры доступных в R цветов: color()[573]
  • RGB кода и функции rgb()
    • значения R, G и B должны быть от 0 до 1: rgb(244/255, 164/255, 96/255)
  • HEX код: “#4c9be8”, “#d9534f”, “#5cb85c”, …

colors()

Показаны первые 125 цветов из 657.

🏠

Один и тот же график можно создать, написав код по-разному.

  • aes задает оси для всех геометрических функций
ggplot(penguins) + 
  aes(x = bill_length_mm, y = bill_depth_mm, color = species) +
  geom_point(size = 3, alpha = 0.8) +
  scale_color_manual(values = c("#e63946", "#ffba49", "#457b9d")) +
  theme_bw()

🏠

Один и тот же график можно создать, написав код по-разному.

  • aes задает оси только для точек - диаграммы разброса
ggplot(penguins) +
  geom_point(
    aes(x = bill_length_mm, y = bill_depth_mm, color = species),
    size = 3, alpha = 0.8) +
  scale_color_manual(values = c("#e63946", "#ffba49", "#457b9d")) +
  theme_bw()

Константа vs переменная

ggplot(
  penguins, 
  aes(
    x = bill_length_mm, 
    y = bill_depth_mm)) + 
  geom_point(color = "sandybrown") +
  theme_bw()

ggplot(
  penguins, 
  aes(
    x = bill_length_mm, 
    y = bill_depth_mm)) + 
  geom_point(aes(color = species)) +
  theme_bw() 

Варианты aes - aesthetics

Для разных geom_ функциий набор доступных aes разный.

Для geom_point():

  • shape - тип символа
  • color - цвет общий / цвет обводки
  • fill - заливка
  • size - размер
  • stroke - толщина обводки
  • alpha - прозрачность

aes переменные - из разных столбцов

Запишем “часть” графика в переменную

p <- ggplot(penguins, aes(x = bill_length_mm, y = bill_depth_mm)) + theme_bw() 
  
p + geom_point(size = 3, alpha = 0.8) 

Color для разных фигур 🏠

Только color, определяет цвет всей фигуры - кружочка.

p +
  geom_point(
    aes(color = species), 
    shape = 16) 

Только color, определяет цвет всей фигуры - окружности.

p + 
  geom_point(
    aes(color = species), 
    shape = 1) 

Color vs fill 🏠

И color, и fill для обводки и заливки.

p + geom_point(aes(fill = species, color = island), shape = 21) 

Цветовая шкала

Задать цвет вручную - scale_color_manual() или scale_fill_manual().

cols3 <- c("#e63946", "#ffba49", "#457b9d")
p_labels <- c("Адели", "Антарктический", "Субантарктический")

p <- p + geom_point(aes(color = species), size = 3, alpha = 0.8) +
  scale_color_manual(values = cols3, labels = p_labels) 

p

Названия осей

p <- p + 
  labs(x = "Длина клюва (мм)", y = "Высота клюва (мм)", color = "Вид")

p

Название графика

p <- p +
  labs(
    title = "Пингвиньи клювы", 
    subtitle = "У трех видов пингвинов очень разные клювики.",
    caption = "Данные: palmerpenguins")
p

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

Текстовые элементы - element_text()

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

Линии - element_line()

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

Границы и фон - element_rect(

Сохранение в файл

После записи в файл, проверяйте, что все сохранилось правильно. Например, размеры итоговой картинки (height и width) могут не подходить для вашего графика - все либо будет слишком мелко, либо элементы будут наезжать друг на друга.

p <- ggplot(...) + ...

ggsave("figures/my_plot.png", plot = p)

ggsave(
  "figures/my_plot.png", p, 
  dpi = 300, width = 10, height = 10, units = "cm") # dpi - разрешение картинки

# В названии файла указываете нужный формат
ggsave("figures/my_plot.pdf", p) 

Если не указать plot = p, то будет сохранен последний нарисованный/выведенный в консоль график.

Сохранение в файл

Более универсальный вариант:

pdf("figures/my_plot.pdf") # Открыть файл для записи - есть и другие функции (png, tiff, ...)
p                          # Нарисовать график
dev.off()                  # Закрыть файл


Либо сохраняйте вручную из RStudio.

В панели Plots: Export -> Save as…

Geoms 🏠

  • geom_point()
  • geom_line()
  • geom_histogram()
  • geom_boxplot()
  • geom_bar() и geom_col()
  • geom_text() и geom_label()
  • точковая диаграмма
  • линейная диаграмма
  • гистограмма
  • диаграмма разброса / боксплот
  • столбчатая диаграмма
  • текст / подписи

Гистограмма - geom_histogram() 🏠

  • нужно указать только x - количественный признак, распределение которого изучаем
  • с помощью fill (или color) можно разделить гистограмму по значениям категориальной переменной на несколько на одном графике
ggplot(penguins, aes(x = flipper_length_mm)) +
  geom_histogram(bins = 25, fill = "sandybrown") +
  labs(title = "Какой длины крылья пингвинов?", 
       x = "Длина крыла (мм)", y = "Число пингвинов") + 
  theme_bw() 

Диаграмма размаха - geom_boxplot() 🏠

  • обычно по x - значения категориальной переменной
  • по y - количественный признак, распределение которого изучаем
  • с помощью fill (или color) можно “разбить” ящики с усами по значениям второй категориальной переменной
penguins %>% drop_na(sex) %>% 
  ggplot(aes(x = species, y = flipper_length_mm, fill = sex)) +
  geom_boxplot() +
  labs(title = "Какой длины крылья пингвинов?", 
       x = "Вид", y = "Длина крыла (мм)", fill = "Пол") + 
  theme_bw() 

Факторы

Категориальные переменные как факторы 🏠

  • Фактор - fct - особый тип данных в R
  • Уровни фактора [levels] - ограниченное число известных значений категориальной переменной, отсортированные в определенном порядке
set.seed(123)

ten_penguins <- penguins %>% 
  slice_sample(n = 10) # случайные 10 строк из датафрейма

ten_penguins$species
 [1] "Gentoo"    "Adelie"    "Gentoo"    "Chinstrap" "Adelie"    "Chinstrap"
 [7] "Gentoo"    "Gentoo"    "Chinstrap" "Gentoo"   

factor() 🏠

Преобразовать какой-то вектор в вектор с факторами:

factor(ten_penguins$species)
 [1] Gentoo    Adelie    Gentoo    Chinstrap Adelie    Chinstrap Gentoo   
 [8] Gentoo    Chinstrap Gentoo   
Levels: Adelie Chinstrap Gentoo


Можем сами задать уровни фактора:

factor(ten_penguins$species, levels = c("Chinstrap", "Adelie", "Gentoo"))
 [1] Gentoo    Adelie    Gentoo    Chinstrap Adelie    Chinstrap Gentoo   
 [8] Gentoo    Chinstrap Gentoo   
Levels: Chinstrap Adelie Gentoo

Задать уровни фактора при отрисовке графика 🏠

ggplot(penguins, 
  aes(
    x = factor(species, levels = c("Chinstrap", "Adelie", "Gentoo")), 
    y = flipper_length_mm,
    fill = species)) +
  geom_boxplot() +
  theme(legend.position = "none")

Создать столбец с факторами 🏠

Обычно оптимальнее заранее создать столбец с факторами или преобразовать столбец с категориями в факторы:

penguins_fct <- penguins %>% 
  mutate(
    species = factor(species, levels = c("Chinstrap", "Adelie", "Gentoo")))

penguins_fct
# A tibble: 344 × 8
   species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
   <fct>   <chr>              <dbl>         <dbl>             <dbl>       <dbl>
 1 Adelie  Torgersen           39.1          18.7               181        3750
 2 Adelie  Torgersen           39.5          17.4               186        3800
 3 Adelie  Torgersen           40.3          18                 195        3250
 4 Adelie  Torgersen           NA            NA                  NA          NA
 5 Adelie  Torgersen           36.7          19.3               193        3450
 6 Adelie  Torgersen           39.3          20.6               190        3650
 7 Adelie  Torgersen           38.9          17.8               181        3625
 8 Adelie  Torgersen           39.2          19.6               195        4675
 9 Adelie  Torgersen           34.1          18.1               193        3475
10 Adelie  Torgersen           42            20.2               190        4250
# ℹ 334 more rows
# ℹ 2 more variables: sex <chr>, year <dbl>

График по датафрейму с факторами 🏠

ggplot(penguins_fct, 
  aes(
    x = species, 
    y = flipper_length_mm,
    fill = species)) +
  geom_boxplot() +
  theme(legend.position = "none")

Пакет forcats 🏠

  • Для работы с факторами есть пакет forcats в составе tidyverse
library(tidyverse)
# или
library(forcats)

fcts <- factor(ten_penguins$species)
fcts
 [1] Gentoo    Adelie    Gentoo    Chinstrap Adelie    Chinstrap Gentoo   
 [8] Gentoo    Chinstrap Gentoo   
Levels: Adelie Chinstrap Gentoo
# В обратном порядке
fct_rev(fcts) %>% levels()
[1] "Gentoo"    "Chinstrap" "Adelie"   
# По частоте встречаемости
fct_infreq(fcts) %>% levels()
[1] "Gentoo"    "Chinstrap" "Adelie"   
# Случайно перемешать
fct_shuffle(fcts) %>% levels()
[1] "Chinstrap" "Adelie"    "Gentoo"   

base R vs forcats 🏠

  • as.factor() сортирует уровни фактора по алфавиту
as.factor(ten_penguins$species)
 [1] Gentoo    Adelie    Gentoo    Chinstrap Adelie    Chinstrap Gentoo   
 [8] Gentoo    Chinstrap Gentoo   
Levels: Adelie Chinstrap Gentoo
  • forcats::as_factor() сортирует уровни фактора по порядку их встречи
as_factor(ten_penguins$species)
 [1] Gentoo    Adelie    Gentoo    Chinstrap Adelie    Chinstrap Gentoo   
 [8] Gentoo    Chinstrap Gentoo   
Levels: Gentoo Adelie Chinstrap

Что такое фактор? 🏠

Строки:

typeof(ten_penguins$species)
[1] "character"
class(ten_penguins$species)
[1] "character"
as.integer(ten_penguins$species)
 [1] NA NA NA NA NA NA NA NA NA NA
sort(ten_penguins$species[c(6:10,1:5)])
 [1] "Adelie"    "Adelie"    "Chinstrap" "Chinstrap" "Chinstrap" "Gentoo"   
 [7] "Gentoo"    "Gentoo"    "Gentoo"    "Gentoo"   

Факторы:

typeof(as_factor(ten_penguins$species))
[1] "integer"
class(as_factor(ten_penguins$species))
[1] "factor"
as.integer(as_factor(ten_penguins$species))
 [1] 1 2 1 3 2 3 1 1 3 1
sort(as_factor(ten_penguins$species)[c(6:10,1:5)])
 [1] Gentoo    Gentoo    Gentoo    Gentoo    Gentoo    Adelie    Adelie   
 [8] Chinstrap Chinstrap Chinstrap
Levels: Gentoo Adelie Chinstrap

Что такое уровни фактора? 🏠

levels(ten_penguins$species)
NULL
levels(as_factor(ten_penguins$species))
[1] "Gentoo"    "Adelie"    "Chinstrap"
as_factor(ten_penguins$species)[1:3]
[1] Gentoo Adelie Gentoo
Levels: Gentoo Adelie Chinstrap

Создание уровней фактора 🏠

some_penguins <- c(ten_penguins$species, "Adelii")

penguin_species_list <- c("Chinstrap", "Adelie", "Gentoo", "Emperor")

some_penguins <- factor(some_penguins, levels = penguin_species_list)
some_penguins
 [1] Gentoo    Adelie    Gentoo    Chinstrap Adelie    Chinstrap Gentoo   
 [8] Gentoo    Chinstrap Gentoo    <NA>     
Levels: Chinstrap Adelie Gentoo Emperor

Убрать лишнее 🏠

fct_drop()

Удалить неиспользуемые уровни фактора: Emperor.

fct_drop(some_penguins)
 [1] Gentoo    Adelie    Gentoo    Chinstrap Adelie    Chinstrap Gentoo   
 [8] Gentoo    Chinstrap Gentoo    <NA>     
Levels: Chinstrap Adelie Gentoo

fct_na_value_to_level()

Приписать отсутствующим уровням (NA) явное название.

fct_na_value_to_level(some_penguins) # level задает название нового уровня
 [1] Gentoo    Adelie    Gentoo    Chinstrap Adelie    Chinstrap Gentoo   
 [8] Gentoo    Chinstrap Gentoo    <NA>     
Levels: Chinstrap Adelie Gentoo Emperor <NA>

Упорядочить уровни фактора 🏠

  • fct_inorder()- упорядочить уровни фактора в порядке встречаемости в векторе
  • fct_infreq() - упорядочить уровни фактора по частоте встречаемости.
  • fct_rev() - изменить порядок уровней на обратный.
  • fct_shuffle() - перемешать уровни

Отсортировать уровни фактора в зависимости от других значений 🏠

  • Функции fct_reorder() и fct_reorder2()

Хотим изобразить распределения длин крыла и расположить ящики по убыванию медианы.

penguins %>% 
  mutate(species = fct_reorder(
    species, flipper_length_mm, .fun = median, na.rm = TRUE, .desc = TRUE)) %>%
  ggplot(aes(x = species, y = flipper_length_mm, fill = species)) +
  geom_boxplot() +
  theme(legend.position = "none")

fct_reorder() 🏠

penguins %>% 
  group_by(species) %>% 
  summarise(mean_fl_length = mean(flipper_length_mm, na.rm = TRUE)) %>% 
  arrange(desc(mean_fl_length))
# A tibble: 3 × 2
  species   mean_fl_length
  <chr>              <dbl>
1 Gentoo              217.
2 Chinstrap           196.
3 Adelie              190.
penguins$species %>% 
  fct_reorder(penguins$flipper_length_mm, .fun = mean, na.rm = TRUE, .desc = TRUE) %>%
  levels()
[1] "Gentoo"    "Chinstrap" "Adelie"   

Объединить редкие категории в одну 🏠

  • Функции семейства fct_lump():
    • fct_lump_n() - оставляет n самых многочисленных уровней, остальные объединяет
    • fct_lump_min() - оставляет уровни, встречающиеся не реже указанного числа раз
    • fct_lump_prop() - оставляет уровни, встречающиеся не чаще указанной частоты
    • fct_lump_lowfreq() - максимально наполняет группу Other так, чтобы она все равно оставалась самой малопредставленной

forcats - что почитать 🏠

Конец!