forked from Pozdniakov/tidy_stats
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path220-base_viz.qmd
118 lines (75 loc) · 11.1 KB
/
220-base_viz.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# Встроенные функции для графиков {#sec-r_vis}
В R есть достаточно мощные встроенные инструменты для визуализации. Я приведу три простых примера: функции `plot()`, `hist()` и `boxplot()`.
## Многоликий `plot()` {#sec-base_plot}
Для примера возьмем датасет `heroes`, вытащим из него колонки `Height` и `Weight` как векторы и применим на них функцию `plot()`.
```{r}
library("tidyverse")
heroes <- read_csv("https://raw.githubusercontent.com/Pozdniakov/tidy_stats/master/data/heroes_information.csv",
na = c("-", "-99"))
```
```{r}
plot(heroes$Height, heroes$Weight)
```
В этом случае будет нарисована **диаграмма рассеяния (точечная диаграмма, *scatterplot),*** где каждая точка задается парой значений из этих векторов: значения из колонки `Height` используются как координаты по оси *x*, а соответствующие значения колонки `Weight` как координаты по оси *y*.
Функция `plot()` - это тоже **универсальная *(generic)*** функция, как и `summary()`(см. @sec-summary). В качестве аргумента можете ей скормить просто один вектор, матрицу, датафрейм. Давайте попробуем использовать функцию `plot()` на встроенном датафрейме `iris`[^220-base_viz-1]:
[^220-base_viz-1]: `iris` -- пожалуй, самый известный набор данных в мире, своего рода *"Hello, world!"* от мира науки о данных. Этот датасет был собран известным ботаником Эдгаром Андерсоном, но стал известен благодаря статье 1936 года известного статистика Роберта Фишера, в которой он использовал эти данные для демонстрации разработанного им метода дискриминантного анализа. С `iris` мы еще столкнемся в главе про многомерные методы анализа (@sec-multivar).
```{r}
iris
```
Каждая строчка -- один цветок ириса, числовые колонки содержат информацию о длине и ширине наружной *(sepal)* и внутренней *(petal)* долях околоцветника, в колонке `Species` содержится название сорта ирисов.
<!--# КАРТИНКА С ИРИСАМИ??? -->
Давайте уберем последнюю колонку, чтобы у нас остались только числовые колонки:
```{r}
iris[, -5]
```
```{r}
plot(iris[, -5])
```
Мы получили таблицу из **диаграмм рассеяния!** Для каждой пары колонок строится отдельная диаграмма рассеяния, что может быть очень удобно при исследовании данных.
Многие пакеты добавляют новые методы `plot()` для объектов из новых классов, поэтому функцию `plot()` имеет смысл пробовать на любых непривычных вам объектах.
## Великая гистограмма {#sec-base_vis_hist}
Другая распространенная функция --- `hist()` --- **гистограмма (histogram)**:
```{r}
weight <- heroes %>%
drop_na(Weight) %>%
pull(Weight)
hist(weight)
```
Гистограмма -- очень простая визуализация, которую при желании несложно нарисовать карандашом на бумаге, следуя простому алгоритму:
1. Весь диапазон значений в выборке делим на интервалы (обычно одинаковые, но можно и разные).
2. Считаем сколько точек попадает в каждый из интервалов.
3. Откладываем высоту столбцов в зависимости от количества точек в каждом интервале.
Главный вопрос здесь: на какие интервалы мы делим? В зависимости от этого гистограмма может выглядеть очень по-разному.
Количество интервалов можно задать самостоятельно с помощью аргумента `breaks =`:
```{r}
hist(weight, breaks = 4)
```
```{r}
hist(weight, breaks = 30)
```
```{r}
hist(weight, breaks = 100)
```
Попробовав различные значения, можно убедиться, что форма гистограммы может достаточно сильно изменяться в зависимости от выбранного количества интервалов[^220-base_viz-2].
[^220-base_viz-2]: На самом деле, функция `hist()` будет использовать заданное количество интервал очень ориентировочно: на основе желаемого количества интервалов будут вычисляться интервалы с круглыми границами.
::: callout-warning
## *Для продвинутых:* правило Стёрджеса и иже с ними
По умолчанию, функция `hist()` использует [**правило Стёрджеса**](https://ru.wikipedia.org/wiki/Правило_Стёрджеса) ***(Sturges' rule)*** для определения количества интервалов гистограммы: $$\displaystyle n=1+\lfloor \log _{2}N\rfloor$$Здесь $N$ -- размер выборки, а $\lfloor \rfloor$ обозначают целую часть числа (т.е. округление вниз). Если мы возьмем вектор `weight`, длина которого 495, то получим 9 интервалов:
```{r}
1 + floor(log(length(weight), base = 2))
```
Правило Стёрджеса -- только один из алгоритмов для расчета количества интервалов в гистограмме! Есть и множество других, например, **правило Фридмана-Диакониса *(Freedman--Diaconis' rule)*** и **правило Скотта *(Scott's normal reference rule).*** Чтобы ими воспользоваться в функции `hist()`, нужно прописать `breaks = "FD"` или `"Scott"` соответственно.
:::
## Нестареющий боксплот {#sec-base_vis_boxplot}
Ну и закончим на суперзвезде прошлого века под названием **ящик с усами *(boxplot with whiskers):***
```{r}
boxplot(Weight ~ Gender, heroes)
```
Здесь мы использовали уже знакомый нам класс формул. Они еще будут нам встречаться дальше, обычно они используются следующим образом: слева от `~` находится зависимая переменная, а справа - "предикторы". Эта интуиция работает и здесь: мы хотим посмотреть, как различается вес в зависимости от пола.
Несмотря на свою популярность, ящик с усами -- достаточно непростой тип графиков. С одной стороны, он неплохо помогает понять, как распределены данные. С другой стороны, немногие знают, как эти ящики и усы рисуются.
Начнем с линии в середине ящика -- это медиана (а не среднее, как могло бы показаться). Низ и верх ящика -- это Q1 и Q3 соответственно. А это значит, что высота ящика -- это разница между Q1 и Q3, т.е. межквартильный размах.
А вот с усами все еще сложнее. Они строятся следующим образом: от края ящика откладываются полтора межквартильных размаха. Но ус рисуется не на этой границе (1.5 IQR), а по крайней точке внутри полутора межквартильных размахов. Если остаются значения за пределами полутора межквартильных размахов, то они отмечаются точками.
<!--# Картинка с боксплотом -->
Очень часто эти точки называют "выбросами", однако это может запутать: нет никакого магического алгоритма, который назначает эти точки выбросами. Точнее, алгоритм есть (и мы его теперь знаем), но в нем нет никакой магии. Почему именно квартили и медиана? А, главное, почему именно полтора межквартильных размаха? Просто так решили. Могли бы взять и 1, и 2, и 1.4, и 1.645 межквартильных размаха, просто потому что (а еще число 1.5 -- число более красивое, чем в 1.4 и 1.645). Это может показаться удивительным, что в статистике, области математики, используются взятые с потолка числа, но скоро мы убедимся, что такое встречается сплошь и рядом.
## Заключение
Возможности R для визуализации очень богатые, и некоторые даже утверждают, что их [более чем достаточно](https://flowingdata.com/2016/03/22/comparing-ggplot2-and-r-base-graphics/). Главное преимущество встроенных функций для графики в R -- возможность быстро нарисовать простой график с помощью одной функции, не подключая никаких дополнительных пакетов. Это делает базовые функции визуализации в R удобными для исследования данных.