🔲 Начинаем с пустого листа

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

Первый, самый важный, и шаг, который программа за вас не сделает - это представить, вообразить график, который вы хотите видеть. То есть быть готовым изобразить его от руки.

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

Эдварад Тафти

https://www.edwardtufte.com

Один из первых теоретиков инфографики.

По Тафти (1982), график должен:

  • показывыть данные;
  • заставить смотрящего задуматься о содержании данных, а не о методе, дизайне, технологии или чем-то еще;
  • избежать искажения того, о чем говорят данные;
  • показать много информации в небольшом пространстве;
  • сделать большой объем данных легким для восприятия;
  • помогать сравнивать разные части информации;
  • демонстрировать разные уровни детализации информации;
  • служить одной из четких целей: описание, открытие, табуляция, или украшение;
  • быть плотно связанным со статистическим и вербальным описанием данных.

Красиво

- заставить смотрящего задуматься о содержании данных, а не о методе, дизайне, технологии или чем-то еще;

- показать много информации в небольшом пространстве;

Соотношение сторон - дело случая?

избежать искажения того, о чем говорят данные;

Визуальные конвенции

Выбор типа графика

Зависит от цели коммуникации, конвенций и типа данных.

http://extremepresentation.typepad.com/files/choosing-a-good-chart-09.pdf

Упростить восприятие

сделать большой объем данных легким для восприятия;

Сравнить

помогать сравнивать разные части информации;

Приблизить, разъяснить

- демонстрировать разные уровни детализации информации;

Тип и цель изображаемой информации

Цели:

  • самому что-то понять о своих данных;
  • объяснить окружающим результаты своего анализа.

Тип:

  • сырые данные (всегда предпочтительно);
  • статистики (коэффициенты, ст.ошибки, индексы, корреляции - всегда менее предпочтительно).

Шарль Минар - Русская кампания Наполеона

Gapminder

https://www.gapminder.org/tools/ Ханса Рослинга

🌈 Выразительные средства

Можно думать о графиках не как об отдельных типах, а как о комбинации отдельных элементов

  • система координат
  • расстояние
  • тип маркера (круг, квадрат, треугольник…)
  • величина маркера (❗️глаз воспринимает только крайние значения)
  • тип линии (сплошные, прерывистые, двойные)
  • толщина линий
  • цвета (линий, заливок)
  • прозрачность
  • цифры и буквы
  • текст: легенды (❗️зло), подписи, заголовки
  • текст: аннотации, сноски

❗️ Каждое из выразительных средств должно соответствовать одной переменной.

Расстояние

Символы

или фигуры: прямоугольники, треугольники, круги, шестиугольники.

Цвета в R

HEX colors - шестизначное обозначение цвета в формате #RRGGBBTT: 0- 9, A-F.

RR - red, GG - green, BB - blue, TT - transparency.

Например,

plot(1:10, type="n", xlab="x", ylab="y")
polygon(c(1, 2, 2, 1), c(2, 2, 4, 4), col="#FF0000") # чистый красный
polygon(c(2, 4, 4, 2), c(2, 2, 4, 4), col="#BF0000") # более темный красный
polygon(c(4, 6, 6, 4), c(2, 2, 4, 4), col="#0000BF") # темный синий
polygon(c(6, 8, 8, 6), c(2, 2, 4, 4), col="#FFFFFF") # белый
polygon(c(8, 9, 9, 8), c(2, 2, 4, 4), col="#000000") # черный

Встроенные colors() - выбрать можно через RStudio -> кнопка Addins -> Color Picker (устанавливается как пакет colourpicker).

Функция rgb(1,0,0, .5) - red, green, blue, transparency.

Готовые наборы цветов:

library(viridis)

data.for.contour <- png::readPNG("images/logo.png")[,,3]

data.for.contour <- (t(data.for.contour)[,nrow(data.for.contour):1])

filled.contour( z=data.for.contour, color.palette = viridis)

Группировка элементов

Система координат

Прежде всего нужно определиться на каком “листе” будем изображать.

Интерактивное поведение

что происходит

  • при наведении мыши на точку
  • при клике на точку
  • при двойном клике
  • при выделении области графика
  • при клике/наведении на другие элементы графика (например легенду)
  • скролле
  • жестах (при использовании смартфонов)

Коммуникация данных

  1. тема. о чем?
  2. кому? аудитория.
  3. зачем?
  4. что именно?
  5. как? баланс между текстом и графикой, деталями и ключевыми выводами, данными и спекуляциями, и т.д.
  6. успех? понять реакцию аудитории.

https://extremepresentation.com/design/audience/

Как и во всех презентациях, коммуникация более успешна если есть история.

Ресурсы для дальнейшего изучения

Онлайн-книга с основами: https://socviz.co/

Бесплатный курс по d3, содержит лекции с теор.основами визуализации данных: https://www.udacity.com/course/data-visualization-and-d3js--ud507

Истории о данных (data stories):

Объяснение результатов исследования широкой публике с использованием методов визуализации, когда у читателей создается впечатление открытия.

Галереи для оценки и вдохновения

Галерея странных графиков: http://xeno.graphics/

Галерея библиотеки d3.js:

🤖 Инструменты

ggplot2

Главный графический пакет.

https://ggplot2.tidyverse.org

ggplot2

gg = Grammar of Graphics, Леланд Вилкинсон https://link.springer.com/content/pdf/10.1007%2F0-387-28695-0.pdf

Слоевая грамматика графики, послоевое построение

График - это данные, представленные с помощью символов.

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

by Leland Wilkinson

Какие переменные, как они обрабатываются, в какой последовательности сортируются значения, какие статистики вычисляются, в каких координатах они размещаются, к какому выразительному средству привязывается каждая переменная и подвергается ли конечной обработке.

Общая структура графиков ggplot2

ggplot(data= ДАННЫЕ,
       mapping = aes( x = переменная1, 
                      y = переменная2,
                      роль1 = переменная3,
                      роль2 = переменная4,
                      и т.п.)
                      )
        ) + #Обязательная часть. Чтобы добавить другие части, в конце нужно ставить плюс, который работает аналогично "трубе".
  
  
  geom_ХХХХХХ(   # вместо ХХХХХ указывается форма графика, например, точечный график point
  aes(меняющиеся характеристики),
      не меняющиеся характеристики, например colour, shape ) +   
  
  scale_ХАРАКТЕРИСТИКА ГЕОМА_ПОДХАРАКТЕРИСТИКА() + # конструирование шкалы и осей 
  
  labs(title, caption, x, y) + # заголовки и подписи
  
  theme() + #  Настройки стилей, не зависящие от значений переменных
  
  coord_flip() + facet_wrap(~ group)  # Дополнительные манипуляции

Не обязательно указывать все эти части, есть удобные умолчания.

Пошаговый пример

Задача: раскрыть взаимосвязь между ростом и весом в зависимости от пола и возраста.

1. Подготовить данные

AT$letter.gender <- sjmisc::rec(AT$gndr, rec="1=Мужчины; 2=Женщины")
AT$weight <- as.vector(AT$weight)
AT$agea <- as.vector(AT$agea)

2. Создаем систему координат

library(ggplot2)
g <-                           # сохраним в объект
  ggplot(data= AT,             # данные
       mapping = aes(          # какие переменные будут задействованы в графике
         x=weight,             # по оси Х
         y=height,             # по оси Y
         colour=letter.gender, # другие характеристики графика , которые варьируют в зависимости от данных
         size=agea)
       )

g # посмотрим, что на этом шаге уже есть

Шаг 2. Добавляем geom, т.е. основную форму графика

# Добавляем формы, в систему координат
g <-  
  g +                   # берем созданную систему координат и через "+" добавляем к нему форму(ы) графика
  geom_point(alpha=.2)  # точечные график. В скобках - неварьирующая характеристика - прозрачность.

g

Шаг 3. Кастомизируем оси и легенду

g <- g+
  
  scale_y_continuous(breaks=seq(110,210,10)) +
  scale_color_discrete(name="Гендер")+
  scale_size_continuous(name="Возраст")
  
g

Шаг 4. Добавляем дополнительные элементы и подписи

g <- g+  
  
  geom_hline(yintercept = mean(AT$height, na.rm=T), col="gray", linetype="dotted")+
  annotate("text", x = 140, y = mean(AT$height, na.rm=T)-2, label="Средний рост", col="gray", size=3)+
  
  # Подписи
  labs(title = "Тяжелее ли более высокие?", 
       caption = "По данным ESS",
       x = "Тяжесть",
       y = "Высота")+

  # Настройки стиля
  theme(  axis.line = element_line(colour = "black"),
          panel.grid = element_blank(),
          plot.caption = element_text(hjust=1),
          plot.title = element_text(size=16, family="Times"),
          plot.background = element_rect(fill="gray90"),
          panel.background = element_rect(fill="gray20"),
          legend.background=element_rect(fill="gray90")
        )

g

Все шаги в одном коде

ggplot(data= AT,  mapping = aes( 
         x=weight,           
         y=height,            
         colour=letter.gender, 
         size=agea))+
  
  geom_point(alpha=.2)+
         
  scale_y_continuous(breaks=seq(110,210,10)) +
  scale_color_discrete(name="Гендер")+
  scale_size_continuous(name="Возраст")+
  
  geom_hline(yintercept = mean(AT$height, na.rm=T), col="gray", linetype="dotted")+
  annotate("text", x = 140, y = mean(AT$height, na.rm=T)-2, label="Средний рост", col="gray", size=3)+
  
  # Подписи
  labs(title = "Тяжелее ли более высокие?", 
       caption = "По данным ESS",
       x = "Тяжесть",
       y = "Высота")+

  # Настройки стиля
  theme(  axis.line = element_line(colour = "black"),
          panel.grid = element_blank(),
          plot.caption = element_text(hjust=1),
          plot.title = element_text(size=16, family="Times"),
          plot.background = element_rect(fill="gray90"),
          panel.background = element_rect(fill="gray20"),
          legend.background=element_rect(fill="gray90")
        )

qplot()

Для быстрого решения без деталей

qplot(x=weight,
       y=height, 
       colour=letter.gender, 
       size=agea,
       alpha=.2,
       geom="point",
       data=AT)

Интерактивные графики

ggiraph

library(ggiraph)

gir1 <- girafe( ggobj = ggplot(AT)+
         geom_point_interactive(
         aes(x = weight,    # "эстетики" - то, что будет варьировать
             y = height, 
             color = letter.gender,
             size = agea,
             tooltip = sport, # всплывающая подсказка (динамический контент)
             data_id= sport, # переменная для использования в hover_css (см. ниже)
             alpha=.4) # не варьирующая часть: прозрачность
               ),
    width_svg = 8, height_svg = 5)               # ширина и высота получаемого графика

girafe_options(x = gir1, opts_hover(css = "fill:black;stroke:orange;r:5pt;"))

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

  • В базовом R - через графические параметры par(mfrow=c(nrow, ncol))
  • В lattice - прямо в формуле через оператор |
  • Для ggplot2:
    • +facet_grid(.~ group),
    • +facet_wrap(.~group, nrow, ncol),
    • gridExtra::grid.arrange().

Дополнения ggplot

🙌 Менее эксплицитные пути построения графиков

𝓡 Base R graphics: plot()

Это обобщенная функция, которая применяет разные методы в зависимости от класса объекта, перемещаемого в аргументы.

  • plot.dendrogram()
  • plot.factor()
  • plot.formula()
  • plot.function()
  • plot.lm()
  • plot.density()
  • и т.д.
plot(weight ~ height, AT)
abline(lm(weight ~ height, AT), col="red")

Lattice

xyplot() / dotplot()

library(lattice)
xyplot(weight ~ height | dom, AT)

# Более насыщенная альтернатива - скаттерплот
car::scatterplot(weight ~ height, AT)

cloud()

library(lattice)
cloud(weight ~ height*agea | gndr==2, AT)

levelplot()

library(lattice)
levelplot(agea ~ height*weight, AT)

bwplot() - Box-whisker plot

library(lattice)
bwplot(height ~ edulvlb | gndr, AT, horizontal=FALSE)

Баки - минимум (+1.5*ИКР от границы ящика) и максимум, ящик - 1 и 3 квартиль, медиана. Отдельные точки - редкие аутлайеры.

histogram()

AT$height <- as.vector(AT$height)

histogram(AT$height)

densityplot

densityplot(AT$height)

📝 Автоматизицазия отчетов

Еще один пример data story: https://ourworldindata.org/happiness-and-life-satisfaction

HTML

Hypertext Markup language Упрощенный язык разметки, позволяющий форматировать текст, добавлять гиперссылки и т.п. Основан на тегах в форме

<h2>Заголовок второго уровня</h2>
<b>Жирный шрифт</b>
<a href="https://google.com> текст ссылки </a>

CSS

Детально стили каждого из классов форматирования можно прописать с помощью CSS - cascade style sheets:

h1 {
    font-family: verdana;
    color: #1b0a48;
  }

https://www.w3schools.com/html/html_css.asp

LaTeX

Еще один язык разметки текста*, но предназначенный для “бумажных” публикаций, ограниченных форматом листа. Хорошо работает с математическими формулами. Устанавливается отдельно.

* Разработчики называют его “издательской системой”

Онлайн-редактор: https://ru.overleaf.com

Rmarkdown

Упрощенный язык форматирования текста, позволяющий комбинировать его c кодом программных языков, в том числе R.

Rmarkdown - его подвид со своими небольшими особенностями.

Различные пакеты могут конвертировать RMarkdown в документы html, а также в word и pdf (с помощью LaTeX)

https://commonmark.org/help/tutorial/

Форматирование текста

# Заголовок первого уровня
## Второго
### Третьего

*Курсив*, или _курсив_

**Жирный**, __Жирный__

~~Зачеркнутый~~

![](изображение.jpg)

[текст ссылки](http://www.ссылка.com)

 Просто текст[^1]
 [^1]: Текст сноски
 

Вставка и опции выполнения кода

“Чанки” кода можно настраивать, что из кода и выдачи показывать

 #```{r, echo=FALSE}
 # код R
 #
 #```
 
 
  # ```{python}
  # myvalues = 2;
  # 
  # ```
  #
  # Можно прямо в текст вставлять `r myvalues`

Вводная часть и настройки

---
title: "Лекция 5 - Визуализация и автоматизированные отчеты"
date: "октябрь 2019"
output:              # опции конвертирования кода
  html_document:     # конвертировать в html
    css: styles1.css # таблица стилей
    df_print: paged  # как отображать таблицы data.frame
    mathjax: null    # библиотека для отображения формул
    toc: yes         # table of contents - добавить?
    toc_depth: '2'   # до какого уровня заголовки отображать?
    toc_float: yes   # прокручивать содержание?
    collapsed: yes   # свернуть содержание до первых заголовоков
    code_folding: hide  # свернуть исходный код в чанках?
    theme: cerulean  # Образцы доступных тем https://bootswatch.com
    include:           
      after_body: footer.html # вставить дополнительный контент
---

Shiny




Максим Руднев, 2018-2021 на основе RMarkdown.