Gggplot2 (сейчас в версии 3.5) – популярный пакет R для визуализаций в анализе данных https://cran.r-project.org/web/packages/ggplot2/index.html
Расширения ggplot2: https://exts.ggplot2.tidyverse.org/gallery/
Gggplot2 разработан командой Х. Уикхема на основе новой грамматики послойной графики.
ggplot2
Каждый график обычно состоит из нескольких слоев
(layers), которые располагаются один над другим. У каждого слоя есть три
обязательных элемента: данные (data),
геом (geom), эстетики
(aes(tetics))
и два вспомогательных: статистические трансформации
(stat) и регулировка положения (position
adjustment).
Данные (data). Собственно, сами данные в виде датафрейма, используемые в данном слое.
Геом (geom). Геом — это сокращение от “геометрический объект”. Собственно, в какой геометрический объект (графический примитив) мы собираемся превращать данные. Например, в точки, прямоугольники или линии.
Отображение (aestetic mappings). Эстетические
отображения или просто эстетики (aestetics) — это набор
правил, как различные переменные превращаются в визуальные особенности
геометрии. Без эстетик остается непонятно, какие именно колонки в
используемом датафрейме превращаются в различные особенности геомов:
позицию, размер, цвет и т.д. У каждого геома (визуального слоя) свой
набор эстетик, но многие из них совпадают у разных геомов (например,
x, y, colour, fill, size) и
могут быть заданы в ggplot()
. Без некоторых эстетик геом не
будет работать. Например, геометрия в виде точек не будет работать без
двух координат этих точек (x и y). Другие эстетики
необязательны и имеют значения по умолчанию. Например, по умолчанию
точки будут черными, но можно сделать их цвет зависимым от выбранной
колонки в датафрейме с помощью эстетики colour.
Статистические трансформации (stat). Название
используемой статистической трансформации (или просто — статистики).
Обычно те же статистические трансформации можно сделать вне
ggplot2
в рамках препроцессинга данных, но с
ggplot2
бывает удобнее. Формально, статистические
трансформации — это обязательный элемент геома, но если вы не хотите
преобразовывать данные, то можете выбрать “identity” преобразование,
которое оставляет все как есть. В ggplot2
у каждого геома
есть статистика по умолчанию, а у каждой статистики - свой геом по
умолчанию. И не всегда статистика по умолчанию — это “identity”
статистика. Например, для барплота (geom_barplot()
)
используется статистика “count”, которая считает частоты, которые затем
трансформируются в высоту барплотов.
Регулировка положения (position adjustment). Регулировка положения — это небольшое улучшение позиции геометрий для части элементов. Например, можно добавить немного случайного шума (“jitter”) в позицию точек, чтобы они не перекрывали друг друга. Или “раздвинуть” (“dodge”) два барплота, чтобы один не загораживал другой. Как и в случае со статистическими трансформациями, в большинстве случаев значение по умолчанию — “identity”.
Кроме слоев, у графика есть:
Координатная система (coord) – нужна для интерпретации координат. Обычно используется декартова система координат (Cartesian coordinate system), т.е. стандартная прямоугольная система координат, но можно использовать и другие, например, полярную систему координат или картографическую проекцию.
Шкалы (scales). Шкалы задают то, как
именно значения превращаются в эстетики. Например, если мы задали,
что разные значения в колонке будут влиять на цвет точки, то какая
именно палитра будет использоваться? В какие конкретно цвета будут
превращаться числовые, логические или строковые значения в колонке? В
ggplot2
есть правила по умолчанию для всех эстестик, и они
отличные, но самостоятельная настройка шкал может значительно улучшить
график.
Фасеты (facets). Фасеты (фасетки) — это одно из
нововведений Уикхэма в грамматику графики. Фасетки повзоляют разбить
график на множество похожих, задав переменную, по которой график будет
разделен. Это очень напоминает использование группировки с помощью
group_by()
.
Тема (theme). Тема — это зрительное оформление
“подложки” графика, не относящейся к содержанию графика: размер шрифта,
цвет фона, размер и цвет линий на фоне и т.д. и т.п. В
ggplot2
есть несколько встроенных тем, а также есть
множество пакетов, которые добавляют дополнительные темы. Кроме того, их
можно настраивать самостоятельно!
Значения по умолчанию (defaults). Если в графике используется несколько слоев, то часто все они используют одни и те же данные и эстетики. Можно задать данные и эстетики по умолчанию для всего графика, чтобы не повторять код.
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.4.0 ✔ purrr 1.0.1
## ✔ tibble 3.2.1 ✔ dplyr 1.1.4
## ✔ tidyr 1.3.0 ✔ stringr 1.5.0
## ✔ readr 2.1.3 ✔ forcats 0.5.2
## Warning: package 'dplyr' was built under R version 4.2.3
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
heroes <- read_csv("https://raw.githubusercontent.com/Pozdniakov/tidy_stats/master/data/heroes_information.csv",
na = c("-", "-99"))
## New names:
## • `` -> `...1`
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 734 Columns: 11
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (8): name, Gender, Eye color, Race, Hair color, Publisher, Skin color, A...
## dbl (3): ...1, Height, Weight
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
str(heroes)
## spc_tbl_ [734 × 11] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ ...1 : num [1:734] 0 1 2 3 4 5 6 7 8 9 ...
## $ name : chr [1:734] "A-Bomb" "Abe Sapien" "Abin Sur" "Abomination" ...
## $ Gender : chr [1:734] "Male" "Male" "Male" "Male" ...
## $ Eye color : chr [1:734] "yellow" "blue" "blue" "green" ...
## $ Race : chr [1:734] "Human" "Icthyo Sapien" "Ungaran" "Human / Radiation" ...
## $ Hair color: chr [1:734] "No Hair" "No Hair" "No Hair" "No Hair" ...
## $ Height : num [1:734] 203 191 185 203 NA 193 NA 185 173 178 ...
## $ Publisher : chr [1:734] "Marvel Comics" "Dark Horse Comics" "DC Comics" "Marvel Comics" ...
## $ Skin color: chr [1:734] NA "blue" "red" NA ...
## $ Alignment : chr [1:734] "good" "good" "good" "bad" ...
## $ Weight : num [1:734] 441 65 90 441 NA 122 NA 88 61 81 ...
## - attr(*, "spec")=
## .. cols(
## .. ...1 = col_double(),
## .. name = col_character(),
## .. Gender = col_character(),
## .. `Eye color` = col_character(),
## .. Race = col_character(),
## .. `Hair color` = col_character(),
## .. Height = col_double(),
## .. Publisher = col_character(),
## .. `Skin color` = col_character(),
## .. Alignment = col_character(),
## .. Weight = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
Запустим функцию ggplot()
, задав наш тиббл
heroes
в качестве данных.
ggplot(data = heroes)
Мы ничего не получили! Это естественно, ведь мы задали только данные по умолчанию, но не задали геометрию и эстетики.
Функция ggplot()
не просто отрисовывает график, эта
функция создает объект класса ggplot
, который можно
сохранить и модифицировать в дальнейшем:
almost_empty_ggplot <- ggplot(data = heroes)
almost_empty_ggplot
Возьмем geom_bar()
для отрисовки барплота. В качестве
эстетик поставим x = Gender
и fill = Gender
.
Поскольку это эстетики, они обозначаются внутри функции параметра
mapping = aes()
или просто внутри функции
aes()
. По умолчанию, geom_bar()
имеет
статистику “count”, что нас полностью устраивает:
geom_bar()
сам посчитает табличку частот и использует
значения Gender
для обозначения позиций и заливки, а
посчитанные частоты будет использовать для задания высоты столбцов.
ggplot(data = heroes) +
geom_bar(aes(x = Gender, fill = Gender))
Сейчас мы сделаем один хитрый трюк: поставим значение эстетики
x = ""
, чтобы собрать все столбики в один.
ggplot(data = heroes) +
geom_bar(aes(x = "", fill = Gender))
Получилось что-то не очень симпатичное, но вполне осмысленное: доли столбца обозначают относительную частоту.
Можно настроить общие параметры геома, не зависящие от данных. Это
нужно делать вне функции aes()
, но внутри функции
для геома.
ggplot(data = heroes) +
geom_bar(aes(x = "", fill = Gender), width = .2)
А теперь внимание! Подумайте, какого действия нам не хватает, чтобы из имеющегося графика получить пайчарт?
ggplot(data = heroes) +
geom_bar(aes(x = "", fill = Gender)) +
coord_polar(theta = "y")
# уберите theta = "y", чтобы понять, что она делает
Нам нужно было всего-лишь поменять систему координат с декартовой на полярную (круговую)! Иначе говоря, пайчарт - это барплот в полярной системе координат.
Именно в этом основная сила грамматики графики и ее реализации в
ggplot2
— вместо того, чтобы описывать и рисовать огромное
количество типов графиков, можно описать практически любой график через
небольшой количество элементарных элементов и правила их соединения.
Получившийся пайчарт осталось подретушировать, убрав все лишние
элементы подложки с помощью самой минималистичной темы
theme_void()
и добавив название графика:
ggplot(data = heroes) +
geom_bar(aes(x = "", fill = Gender)) +
#coord_polar(theta = "y") +
theme_void() +
labs(title = "Gender distributions for superheroes")
hapax <- load("/Users/olgaliashevskaia/Documents/Vyshka/DA-for-CL2023/data/HapaxPlato.rdata")
str(hapax)
ggplot(data=hapax, aes(x=hapax, y=words)) +
geom_point()
Для этого примера мы возьмем мета-анализ связи количества лет обучения и интеллекта: “How Much Does Education Improve Intelligence? A Meta-Analysis” [@eduiq]. Мета-анализ — это группа статистических методов, которые позволяют объединить результаты нескольких исследований с похожим планом исследованием и тематикой, чтобы посчитать средний эффект между несколькими статьями сразу.
Данные и скрипт для анализа данных в этой статье находятся в открытом доступе: https://osf.io/r8a24/
Полный текст статьи доступен по ссылке.
Существует положительная корреляция между количеством лет, который
человек потратил на обучение, и интеллектом. Это может объясняться
по-разному: как то, что обучение повышает интеллект, и как то, что люди
с высоким интеллекте стремятся получать больше образования. Напрямую в
эксперименте это проверить нельзя, поэтому есть несколько
квази-экспериментальных планов, которые косвенно указывают на верность
той или иной гипотезу. Например, если в стране изменилось количество лет
обязательного школьного образования, то повлияло ли это на интеллект
целого поколения? Или все-таки дело в Моргенштерне
Данная картинка показывает, насколько размер эффекта (выраженный в баллах IQ) зависит от того, какой средний возраст участвоваших в исследовании испытуемых.
Каждая точка на этом графике — это отдельное исследование, положение по оси x — средний возраст респондентов, а положение по оси y - средний прирост интеллекта согласно исследованию. Размер точки отражает “точность” исследования (грубо говоря, чем больше выборка, тем больше точка). Два графика обозначают два квазиэкспериментальных плана.
Мы сфокусируемся на нижней картинке с “Policy change” — это как раз исследования, в которых изучается изменения интеллекта в возрастных группах после изменения количества лет обучения в школе.
Мы полностью воспроизведем код
library(tidyverse)
Заметьте, данный датасет использует формат хранения данных tsv. Попытайтесь самостоятельно прочитать его.
df <- read_tsv("https://raw.githubusercontent.com/Pozdniakov/tidy_stats/master/data/meta_dataset.txt")
## Rows: 142 Columns: 17
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr (2): Country, Design
## dbl (15): Study_ID, Data_ID, k, n, outcome_test_cat, Effect_size, SE, Outcom...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Давайте посмотрим, как устроен датафрейм df
:
df
## # A tibble: 142 × 17
## Study_ID Data_ID k Country n Design outcome_test_cat Effect_size
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <dbl> <dbl>
## 1 1 1 4 UK 483 Control Pr… 0 0.778
## 2 1 1 4 UK 290 Control Pr… 1 0.0771
## 3 1 1 4 UK 290 Control Pr… 1 0.427
## 4 1 1 4 UK 288 Control Pr… 1 0.00519
## 5 1 2 13 UK 1017 Control Pr… 0 1.62
## 6 1 2 13 UK 1022 Control Pr… 1 0.915
## 7 1 2 13 UK 1021 Control Pr… 1 0.305
## 8 1 2 13 UK 981 Control Pr… 1 0.719
## 9 1.5 2 13 UK 1024 Control Pr… 1 1.70
## 10 1.5 2 13 UK 1023 Control Pr… 1 1.78
## # ℹ 132 more rows
## # ℹ 9 more variables: SE <dbl>, Outcome_age <dbl>, quasi_age <dbl>,
## # cpiq_early_age <dbl>, cpiq_age_diff <dbl>, ses_funnel <dbl>,
## # published <dbl>, Male_only <dbl>, Achievement <dbl>
Каждая строчка — это результат отдельного исследования, при этом одна статья может включать несколько исследований,
В дальнейшем мы будем использовать код авторов статьи и смотреть, строчка за строчкой, как он будет работать.
cpiq <- subset(df, subset=(Design=="Control Prior IQ"))
poli <- subset(df, subset=(Design=="Policy Change"))
Авторы исследования используют subset()
, это функция
базового R, принцип которой очень похож на filter()
1.
Итак, начнем рисовать сам график. Сначала иницируем объект
ggplot
с данными poli
по умолчанию.
poli |>
ggplot()
Теперь добавим в качестве эстетик по умолчанию координаты:
aes(x=Outcome_age, y=Effect_size)
.
cpiq <- subset(df, subset=(Design=="Control Prior IQ"))
poli <- subset(df, subset=(Design=="Policy Change"))
poli |>
ggplot(aes(x=Outcome_age, y=Effect_size))
Что изменилось? Появилась координатная ось и шкалы. Заметьте, масштаб неслучаен: он строится на основе разброса значений в выбранных колонках. Однако этого недостаточно для отрисовки графика, нехватает геометрии: нужно задать, в какую географическую сущность отобразятся данные.
ggplot(aes(x=Outcome_age, y=Effect_size), data=poli) +
geom_point()
Готово! Это и есть основа картинки. Добавляем размер:
poli
## # A tibble: 30 × 17
## Study_ID Data_ID k Country n Design outcome_test_cat Effect_size
## <dbl> <dbl> <dbl> <chr> <dbl> <chr> <dbl> <dbl>
## 1 5 8 1 Sweden 142221 Policy Ch… 0 1.31
## 2 6 9 1 Norway 107223 Policy Ch… 0 3.69
## 3 7 10 2 USA 11427 Policy Ch… 1 4.95
## 4 7 10 2 USA 11427 Policy Ch… 1 2.85
## 5 9 12 4 UK 2385 Policy Ch… 1 5.1
## 6 9 12 4 UK 2057 Policy Ch… 1 4.65
## 7 9 12 4 UK 1963 Policy Ch… 1 0.15
## 8 9 12 4 UK 1701 Policy Ch… 1 0.75
## 9 10 13 2 UK 1860 Policy Ch… 1 2.61
## 10 10 13 2 UK 1860 Policy Ch… 1 3.54
## # ℹ 20 more rows
## # ℹ 9 more variables: SE <dbl>, Outcome_age <dbl>, quasi_age <dbl>,
## # cpiq_early_age <dbl>, cpiq_age_diff <dbl>, ses_funnel <dbl>,
## # published <dbl>, Male_only <dbl>, Achievement <dbl>
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point()
Перед нами возникла проблема оверплоттинга: некоторые точки
перекрывают друг друга, поскольку имеют очень близкие координат. Авторы
графика решают эту проблему очевидным способом: добавляют прозрачности
точкам. Заметьте, прозрачность задается для всех точек одним значением,
поэтому параметр alpha
задается вне функции
aes()
.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55)
Совершенно так же задается и цвет. Он задается одинаковым для всех точек с помощью HEX-кода.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="#BA1825")
Теперь добавим регрессионную прямую с доверительными интервалами на
график. Это специальный геом geom_smooth()
со специальной
статистикой, который займет второй слой данного графика.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="#BA1825") +
geom_smooth()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
## Warning: The following aesthetics were dropped during statistical transformation: size
## ℹ This can happen when ggplot fails to infer the correct grouping structure in
## the data.
## ℹ Did you forget to specify a `group` aesthetic or to convert a numerical
## variable into a factor?
По умолчанию geom_smooth()
строит кривую линию. Поставим
method = "lm"
для прямой.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="#BA1825") +
geom_smooth(method="lm")
## `geom_smooth()` using formula = 'y ~ x'
## Warning: The following aesthetics were dropped during statistical transformation: size
## ℹ This can happen when ggplot fails to infer the correct grouping structure in
## the data.
## ℹ Did you forget to specify a `group` aesthetic or to convert a numerical
## variable into a factor?
Теперь нужно поменять цвет: ярко синий цвет, используемый по умолчанию здесь попросту мешает восприятию графика.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.5, colour="darkgreen") +
geom_smooth(method="lm", colour="darkgreen")
## `geom_smooth()` using formula = 'y ~ x'
## Warning: The following aesthetics were dropped during statistical transformation: size
## ℹ This can happen when ggplot fails to infer the correct grouping structure in
## the data.
## ℹ Did you forget to specify a `group` aesthetic or to convert a numerical
## variable into a factor?
Авторы графика перекрашивают серую полупрозначную область тоже. В
этом случае используется параметр fill =
, а не
colour =
, но цвет используется тот же.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(colour="darkgreen", alpha=.55) +
geom_smooth(method="lm", colour="darkgreen", fill="darkgreen")
## `geom_smooth()` using formula = 'y ~ x'
## Warning: The following aesthetics were dropped during statistical transformation: size
## ℹ This can happen when ggplot fails to infer the correct grouping structure in
## the data.
## ℹ Did you forget to specify a `group` aesthetic or to convert a numerical
## variable into a factor?
Регрессионную линию авторы немного утоньшают с помощью параметра
size =
.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="#BA1825") +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825", size=.5)
## `geom_smooth()` using formula = 'y ~ x'
Чтобы сместить фокус в сторону точек, авторы добавляют прозрачности
для всего geom_smooth()
.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="#BA1825") +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825",size=.5, alpha=.25)
## `geom_smooth()` using formula = 'y ~ x'
На шкале присутствует 0, и по умолчанию он никак не обозначен. Это
легко исправить с помощью вспомогательного геома
geom_hline()
.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="#BA1825") +
geom_hline(yintercept=0) +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825",size=.5, alpha=.25)
## `geom_smooth()` using formula = 'y ~ x'
Оттенить эту линию можно, сделав ее пунктирной.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="#BA1825") +
geom_hline(yintercept=0, linetype="dotted") +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825",size=.5, alpha=.25)
## `geom_smooth()` using formula = 'y ~ x'
Авторы графика вручную задают деления шкалы по оси x.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="#BA1825") +
geom_hline(yintercept=0, linetype="dotted") +
scale_x_continuous(breaks=c(20,30,40,50,60,70,80)) +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825",size=.5, alpha=.25)
## `geom_smooth()` using formula = 'y ~ x'
С помощью функции guides()
убирают легенду с
картинки.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="#BA1825") +
geom_hline(yintercept=0, linetype="dotted") +
scale_x_continuous(breaks=c(20,30,40,50,60,70,80)) +
guides(size=F) +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825",size=.5, alpha=.25)
## Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as
## of ggplot2 3.3.4.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `geom_smooth()` using formula = 'y ~ x'
Следующим этапом авторы добавляют подписи шкал и название картинки.
Обратите внимание на \n
внутри подписи к оси y,
которая задает перенос на следующую строку.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="darkgreen") +
geom_hline(yintercept=0, linetype="dotted") +
scale_x_continuous(breaks=c(20,30,40,50,60,70,80)) +
xlab("Age at outcome test (years)") +
ylab("Gain for 1 year of education\n(IQ points)") +
guides(size=F) +
geom_smooth(method="lm", colour="darkgreen",fill="darkgreen",size=.5, alpha=.25) +
ggtitle("Policy Change")
## `geom_smooth()` using formula = 'y ~ x'
Теперь пришло время сделать график более красивым и понятным с
помощью изменения подложки, т.е. работы с темой графика. Здесь тема
задается сначала как theme_bw()
— встроенная в
ggplot2
минималистичная тема, а потом через функцию
theme()
, через которую можно управлять конкретными
элементами темы. Здесь это сделано, чтобы передвинуть название графика к
центру.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=poli) +
geom_point(alpha=.55, colour="#BA1825") +
geom_hline(yintercept=0, linetype="dotted") +
theme_bw() +
scale_x_continuous(breaks=c(20,30,40,50,60,70,80), limits = c(0, 90)) +
xlab("Age at outcome test (years)") +
ylab("Gain for 1 year of education\n(IQ points)") +
guides(size=F) +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825",size=.5, alpha=.25) +
ggtitle("Policy Change") +
theme(plot.title = element_text(hjust=0.5))
## `geom_smooth()` using formula = 'y ~ x'
Готово! Мы полностью воспроизвели график авторов статьи с помощью их открытого кода.
Если вы помните, то в изначальном графике было две картинки. Авторы делают их отдельно, с помощью почти идентичного кода. Нечто похожее можно сделать по-другому, применяя фасетки.
Для этого мы возьмем неотфильтрованный датасет df
, а с
помощью колонки Design
, на основании которой разделялся
датасет для графиков, произведем разделение графиков внутри самого
ggplot
объекта. Для этого нам понадобится функция
facet_wrap()
, в которой с помощью формулы можно задать
колонки, по которым будут разделены картинки по вертикали (слева от ~) и
горизонтально (справа от ~). Пробуем разделить графики
горизонтально:
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=df) +
geom_point(alpha=.55, colour="#BA1825") +
geom_hline(yintercept=0, linetype="dotted") +
theme_bw() +
scale_x_continuous(breaks=c(20,30,40,50,60,70,80)) +
xlab("Age at outcome test (years)") +
ylab("Gain for 1 year of education\n(IQ points)") +
guides(size=F) +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825",size=.5, alpha=.25) + ggtitle("Policy Change")+
theme(plot.title = element_text(hjust=0.5)) +
facet_wrap(~Design)
## `geom_smooth()` using formula = 'y ~ x'
Здесь становится очевидно, почему авторы не включали данные
"School Age Cutoff"
третьим графиком: средний возраст
участников этих исследований сильно отличается.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)),
data=df |>
filter(Design != "School Age Cutoff")) +
geom_point(alpha=.55, colour="#BA1825") +
geom_hline(yintercept=0, linetype="dotted") +
theme_bw() +
scale_x_continuous(breaks=c(20,30,40,50,60,70,80)) +
xlab("Age at outcome test (years)") +
ylab("Gain for 1 year of education\n(IQ points)") +
guides(size=F) +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825",size=.5, alpha=.25) + ggtitle("Policy Change")+
theme(plot.title = element_text(hjust=0.5)) +
facet_wrap(~Design)
## `geom_smooth()` using formula = 'y ~ x'
Теперь поставим два графика друг над другом, поместив
Design
слева от ~
внутри
facet_wrap()
. Справа нужно добавить точку.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=df |> filter(Design != "School Age Cutoff")) +
geom_point(alpha=.55, colour="#BA1825") +
geom_hline(yintercept=0, linetype="dotted") +
theme_bw() +
scale_x_continuous(breaks=c(20,30,40,50,60,70,80)) +
xlab("Age at outcome test (years)") +
ylab("Gain for 1 year of education\n(IQ points)") +
guides(size=F) +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825",size=.5, alpha=.25) + ggtitle("Policy Change")+
theme(plot.title = element_text(hjust=0.5)) +
facet_grid(Design~.)
## `geom_smooth()` using formula = 'y ~ x'
Теперь нужно изменить подписи.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2)), data=df |> filter(Design != "School Age Cutoff")) +
geom_point(alpha=.55, colour="#BA1825") +
geom_hline(yintercept=0, linetype="dotted") +
theme_bw() +
scale_x_continuous(breaks=c(20,30,40,50,60,70,80)) +
xlab("Age at outcome test (years)") +
ylab("Gain for 1 year of education\n(IQ points)") +
guides(size=F) +
geom_smooth(method="lm", colour="#BA1825",fill="#BA1825",size=.5, alpha=.25) +
ggtitle("Effect of education as a function of age at the outcome test")+
theme(plot.title = element_text(hjust=0.5)) +
facet_grid(Design~.)
## `geom_smooth()` using formula = 'y ~ x'
Чтобы акцентировать графики, можно раскрасить их в разные цвета в
дополнение к фасеткам. Для этого мы переносим colour =
и
fill =
из параметров соответствующих геомов внутрь эстетик
и делаем зависимыми от Design
. Поскольку эти эстетики
(точнее, colour =
) одинаковы заданы для двух геомов
(geom_point()
и geom_smooth()
), то мы спокойно
можем вынести их в эстетики по умолчанию — в параметры
aes()
внутри ggplot()
.
При этом сразу выключим легенды для новых эстетик, потому они избыточны.
ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2), colour = Design, fill = Design), data=df |> filter(Design != "School Age Cutoff")) +
geom_point(alpha=.55) +
geom_hline(yintercept=0, linetype="dotted") +
theme_bw() +
scale_x_continuous(breaks=c(20,30,40,50,60,70,80)) +
xlab("Age at outcome test (years)") +
ylab("Gain for 1 year of education\n(IQ points)") +
guides(size=FALSE, colour = FALSE, fill = FALSE) +
geom_smooth(method="lm", size=.5, alpha=.25) +
ggtitle("Effect of education as a function of age at the outcome test")+
theme(plot.title = element_text(hjust=0.5)) +
facet_grid(Design~.)
## `geom_smooth()` using formula = 'y ~ x'
Слишком блеклая палитра? Не беда, можно задать палитру вручную! В
ggplot2
встроены легендарные Brewer’s Color
Palettes, которыми мы и воспользуемся.
Функции для шкал устроены интересным образом: они состоят из трех
слов, первое из которых scale_*_*()
, второе — эстетика,
например, scale_color_*()
, а последнее слово — тип самой
шкалы, в некоторых случаях - специальное название для используемой
шкалы, как и в случае с scale_color_brewer()
.
meta_2_gg <- ggplot(aes(x=Outcome_age, y=Effect_size, size=1/(SE^2), colour = Design, fill = Design), data=df |> filter(Design != "School Age Cutoff")) +
geom_point(alpha=.55) +
geom_hline(yintercept=0, linetype="dotted") +
theme_bw() +
scale_x_continuous(breaks=c(20,30,40,50,60,70,80)) +
xlab("Age at outcome test (years)") +
ylab("Gain for 1 year of education\n(IQ points)") +
guides(size=FALSE, colour = FALSE, fill = FALSE) +
geom_smooth(method="lm", size=.5, alpha=.25) +
ggtitle("Effect of education as a function of age at the outcome test")+
theme(plot.title = element_text(hjust=0.5)) +
facet_grid(Design~.)+
scale_colour_brewer(palette = "Set1")+
scale_fill_brewer(palette = "Set1")
meta_2_gg
## `geom_smooth()` using formula = 'y ~ x'
ggplot2
ggplot2
стал очень популярным пакетом и быстро обзавелся
расширениями - пакетами R, которые являются надстройками над
ggplot2
. Эти расширения бывают самого разного рода,
например, добавляющие дополнительные геомы или просто реализующие
отдельные типы графиков на языке ggplot2
.
Я рекомендую посмотреть самостоятельно галерею расширений
ggplot2
: https://exts.ggplot2.tidyverse.org/gallery/
Для примера мы возьмем пакет hrbrthemes
, который
предоставляет дополнительные темы для ggplot2
, компоненты
тем и шкалы.
#install.packages("hrbrthemes")
library(hrbrthemes)
meta_2_gg +
theme_ipsum()
## `geom_smooth()` using formula = 'y ~ x'
Функция ggsave()
(аналог в базовом R -
save()
)
plot <- ggplot(data=iris, aes(x=Sepal.Length, y=Sepal.Width)) +
geom_point(aes(shape=Species, color=Species))
# setwd("/Users/olgaliashevskaia/Desktop")
ggsave("plot1.png")
## Saving 7 x 5 in image
ggsave(plot, file="plot2.png")
## Saving 7 x 5 in image
ggsave(plot, file="plot3.png", width=6, height=4)
Датасет homo
: исследование связи между акустическим
сигналом и восприятием гендерной ориентации говорящих (кантонский
диалект китайского языка). В экспериментах использовался перцептивный
тест и сбор суждений относительно 14 говорящих.
homo <- read_csv("https://raw.githubusercontent.com/LingData2019/LingData2020/master/data/orientation.csv")
## Rows: 14 Columns: 10
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): speaker, orientation
## dbl (8): s.duration.ms, vowel.duration.ms, average.f0.Hz, f0.range.Hz, perce...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(homo)
## # A tibble: 6 × 10
## speaker s.duration.ms vowel.duration.ms average.f0.Hz f0.range.Hz
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 A 61.4 113. 120. 52.5
## 2 B 63.9 126. 100. 114
## 3 C 55.1 127. 115. 103.
## 4 D 78.1 119. 127. 58.8
## 5 E 64.7 93.7 131. 37.4
## 6 F 67 128. 151. 42
## # ℹ 5 more variables: perceived.as.homo <dbl>, perceived.as.hetero <dbl>,
## # perceived.as.homo.percent <dbl>, orientation <chr>, age <dbl>
s.duration.ms vs. vowel.duration.ms
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms)) +
geom_point()
Добавьте цвет по столбцу color = orientation
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms,
color = orientation)) +
geom_point()
Вместо цвета shape
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms,
shape = orientation)) +
geom_point(color = "darkred")
Используйте параметр size в эстетике, чтобы отобразить возраст:
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms,
size = age)) +
geom_point()
Измените цвет точек и добавьте метки:
homo |>
mutate(label = ifelse(orientation == "homo","⚣", "⚤")) |>
ggplot(aes(s.duration.ms, vowel.duration.ms, label = label, fill = orientation)) +
geom_label()
Используйте цвет (color) вместо заполнения (fill):
homo |>
mutate(label = ifelse(orientation == "homo","⚣", "⚤")) |>
ggplot(aes(s.duration.ms, vowel.duration.ms, label = label, color = orientation)) +
geom_text()
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms)) +
geom_point()+
xlab("duration of [s] in ms")+
ylab("vowel duration in ms")
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms)) +
geom_point()+
xlab("duration of [s] in ms") +
ylab("vowel duration in ms") +
theme_minimal()
freq <- read_csv("https://raw.githubusercontent.com/LingData2019/LingData/master/data/freqrnc2011_1000.csv")
## Rows: 1000 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): lemma
## dbl (2): freq_ipm, rank
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
freq |>
ggplot(aes(rank, freq_ipm)) +
geom_point(alpha = .3) +
labs(x = "rank", y = "ipm") +
theme_minimal()
Use scale_y_log10() to transform the y axis:
freq |>
ggplot(aes(1:1000, freq_ipm)) +
geom_point(alpha = .3) +
geom_smooth(method=lm)+
xlab("rank") +
ylab("log(ipm)") +
scale_y_log10() +
scale_x_log10() +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms, color = orientation)) +
geom_point() +
geom_rug() +
theme_minimal()
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms)) +
geom_point() +
geom_hline(yintercept = mean(homo$vowel.duration.ms))+
geom_vline(xintercept = 60) +
theme_minimal()
Change line types and color:
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms)) +
geom_point() +
geom_hline(yintercept = 120, linetype = 4) +
geom_vline(xintercept = 60, color = "blue") +
theme_minimal()
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms)) +
geom_point()+
annotate(geom = "rect", xmin = 77, xmax = 79,
ymin = 117, ymax = 122, fill = "red", alpha = 0.2) +
annotate(geom = "text", x = 75, y = 125,
label = "Who is that?\n Outlier?") +
theme_minimal()
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms)) +
geom_point() +
geom_hline(yintercept = 120, linetype = 4) +
geom_vline(xintercept = 60, color = "blue") +
geom_smooth(method = "lm") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
Try geom_smooth() without arguments now!
facet_wrap
– cf. group_by
in dplyr
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms)) +
geom_point() +
# geom_hline(yintercept = 120, linetype = 4) +
# geom_vline(xintercept = 60, color = "blue") +
# geom_smooth(method = "lm") +
facet_wrap(orientation~.)
theme_minimal()
## List of 94
## $ line :List of 6
## ..$ colour : chr "black"
## ..$ linewidth : num 0.5
## ..$ linetype : num 1
## ..$ lineend : chr "butt"
## ..$ arrow : logi FALSE
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_line" "element"
## $ rect :List of 5
## ..$ fill : chr "white"
## ..$ colour : chr "black"
## ..$ linewidth : num 0.5
## ..$ linetype : num 1
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_rect" "element"
## $ text :List of 11
## ..$ family : chr ""
## ..$ face : chr "plain"
## ..$ colour : chr "black"
## ..$ size : num 11
## ..$ hjust : num 0.5
## ..$ vjust : num 0.5
## ..$ angle : num 0
## ..$ lineheight : num 0.9
## ..$ margin : 'margin' num [1:4] 0points 0points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : logi FALSE
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ title : NULL
## $ aspect.ratio : NULL
## $ axis.title : NULL
## $ axis.title.x :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 1
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 2.75points 0points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.title.x.top :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 0
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 2.75points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.title.x.bottom : NULL
## $ axis.title.y :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 1
## ..$ angle : num 90
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 2.75points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.title.y.left : NULL
## $ axis.title.y.right :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 0
## ..$ angle : num -90
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 0points 2.75points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.text :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : chr "grey30"
## ..$ size : 'rel' num 0.8
## ..$ hjust : NULL
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.text.x :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 1
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 2.2points 0points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.text.x.top :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 0
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 2.2points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.text.x.bottom : NULL
## $ axis.text.y :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : num 1
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 2.2points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.text.y.left : NULL
## $ axis.text.y.right :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : num 0
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 0points 2.2points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.ticks : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ axis.ticks.x : NULL
## $ axis.ticks.x.top : NULL
## $ axis.ticks.x.bottom : NULL
## $ axis.ticks.y : NULL
## $ axis.ticks.y.left : NULL
## $ axis.ticks.y.right : NULL
## $ axis.ticks.length : 'simpleUnit' num 2.75points
## ..- attr(*, "unit")= int 8
## $ axis.ticks.length.x : NULL
## $ axis.ticks.length.x.top : NULL
## $ axis.ticks.length.x.bottom: NULL
## $ axis.ticks.length.y : NULL
## $ axis.ticks.length.y.left : NULL
## $ axis.ticks.length.y.right : NULL
## $ axis.line : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ axis.line.x : NULL
## $ axis.line.x.top : NULL
## $ axis.line.x.bottom : NULL
## $ axis.line.y : NULL
## $ axis.line.y.left : NULL
## $ axis.line.y.right : NULL
## $ legend.background : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ legend.margin : 'margin' num [1:4] 5.5points 5.5points 5.5points 5.5points
## ..- attr(*, "unit")= int 8
## $ legend.spacing : 'simpleUnit' num 11points
## ..- attr(*, "unit")= int 8
## $ legend.spacing.x : NULL
## $ legend.spacing.y : NULL
## $ legend.key : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ legend.key.size : 'simpleUnit' num 1.2lines
## ..- attr(*, "unit")= int 3
## $ legend.key.height : NULL
## $ legend.key.width : NULL
## $ legend.text :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : 'rel' num 0.8
## ..$ hjust : NULL
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ legend.text.align : NULL
## $ legend.title :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : num 0
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ legend.title.align : NULL
## $ legend.position : chr "right"
## $ legend.direction : NULL
## $ legend.justification : chr "center"
## $ legend.box : NULL
## $ legend.box.just : NULL
## $ legend.box.margin : 'margin' num [1:4] 0cm 0cm 0cm 0cm
## ..- attr(*, "unit")= int 1
## $ legend.box.background : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ legend.box.spacing : 'simpleUnit' num 11points
## ..- attr(*, "unit")= int 8
## $ panel.background : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ panel.border : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ panel.spacing : 'simpleUnit' num 5.5points
## ..- attr(*, "unit")= int 8
## $ panel.spacing.x : NULL
## $ panel.spacing.y : NULL
## $ panel.grid :List of 6
## ..$ colour : chr "grey92"
## ..$ linewidth : NULL
## ..$ linetype : NULL
## ..$ lineend : NULL
## ..$ arrow : logi FALSE
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_line" "element"
## $ panel.grid.major : NULL
## $ panel.grid.minor :List of 6
## ..$ colour : NULL
## ..$ linewidth : 'rel' num 0.5
## ..$ linetype : NULL
## ..$ lineend : NULL
## ..$ arrow : logi FALSE
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_line" "element"
## $ panel.grid.major.x : NULL
## $ panel.grid.major.y : NULL
## $ panel.grid.minor.x : NULL
## $ panel.grid.minor.y : NULL
## $ panel.ontop : logi FALSE
## $ plot.background : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ plot.title :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : 'rel' num 1.2
## ..$ hjust : num 0
## ..$ vjust : num 1
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 5.5points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ plot.title.position : chr "panel"
## $ plot.subtitle :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : num 0
## ..$ vjust : num 1
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 5.5points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ plot.caption :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : 'rel' num 0.8
## ..$ hjust : num 1
## ..$ vjust : num 1
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 5.5points 0points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ plot.caption.position : chr "panel"
## $ plot.tag :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : 'rel' num 1.2
## ..$ hjust : num 0.5
## ..$ vjust : num 0.5
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ plot.tag.position : chr "topleft"
## $ plot.margin : 'margin' num [1:4] 5.5points 5.5points 5.5points 5.5points
## ..- attr(*, "unit")= int 8
## $ strip.background : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ strip.background.x : NULL
## $ strip.background.y : NULL
## $ strip.clip : chr "inherit"
## $ strip.placement : chr "inside"
## $ strip.text :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : chr "grey10"
## ..$ size : 'rel' num 0.8
## ..$ hjust : NULL
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 4.4points 4.4points 4.4points 4.4points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ strip.text.x : NULL
## $ strip.text.y :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : NULL
## ..$ angle : num -90
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ strip.switch.pad.grid : 'simpleUnit' num 2.75points
## ..- attr(*, "unit")= int 8
## $ strip.switch.pad.wrap : 'simpleUnit' num 2.75points
## ..- attr(*, "unit")= int 8
## $ strip.text.y.left :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : NULL
## ..$ angle : num 90
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## - attr(*, "class")= chr [1:2] "theme" "gg"
## - attr(*, "complete")= logi TRUE
## - attr(*, "validate")= logi TRUE
Another option: facet_grid
homo |>
ggplot(aes(s.duration.ms, vowel.duration.ms, colour = orientation, fill = orientation)) +
geom_point() +
# geom_hline(yintercept = 120, linetype = 4) +
# geom_vline(xintercept = 60, color = "blue") +
# geom_smooth(method = "lm") +
facet_grid(orientation~.)
theme_minimal()
## List of 94
## $ line :List of 6
## ..$ colour : chr "black"
## ..$ linewidth : num 0.5
## ..$ linetype : num 1
## ..$ lineend : chr "butt"
## ..$ arrow : logi FALSE
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_line" "element"
## $ rect :List of 5
## ..$ fill : chr "white"
## ..$ colour : chr "black"
## ..$ linewidth : num 0.5
## ..$ linetype : num 1
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_rect" "element"
## $ text :List of 11
## ..$ family : chr ""
## ..$ face : chr "plain"
## ..$ colour : chr "black"
## ..$ size : num 11
## ..$ hjust : num 0.5
## ..$ vjust : num 0.5
## ..$ angle : num 0
## ..$ lineheight : num 0.9
## ..$ margin : 'margin' num [1:4] 0points 0points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : logi FALSE
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ title : NULL
## $ aspect.ratio : NULL
## $ axis.title : NULL
## $ axis.title.x :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 1
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 2.75points 0points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.title.x.top :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 0
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 2.75points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.title.x.bottom : NULL
## $ axis.title.y :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 1
## ..$ angle : num 90
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 2.75points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.title.y.left : NULL
## $ axis.title.y.right :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 0
## ..$ angle : num -90
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 0points 2.75points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.text :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : chr "grey30"
## ..$ size : 'rel' num 0.8
## ..$ hjust : NULL
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.text.x :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 1
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 2.2points 0points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.text.x.top :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : num 0
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 2.2points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.text.x.bottom : NULL
## $ axis.text.y :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : num 1
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 2.2points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.text.y.left : NULL
## $ axis.text.y.right :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : num 0
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 0points 2.2points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ axis.ticks : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ axis.ticks.x : NULL
## $ axis.ticks.x.top : NULL
## $ axis.ticks.x.bottom : NULL
## $ axis.ticks.y : NULL
## $ axis.ticks.y.left : NULL
## $ axis.ticks.y.right : NULL
## $ axis.ticks.length : 'simpleUnit' num 2.75points
## ..- attr(*, "unit")= int 8
## $ axis.ticks.length.x : NULL
## $ axis.ticks.length.x.top : NULL
## $ axis.ticks.length.x.bottom: NULL
## $ axis.ticks.length.y : NULL
## $ axis.ticks.length.y.left : NULL
## $ axis.ticks.length.y.right : NULL
## $ axis.line : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ axis.line.x : NULL
## $ axis.line.x.top : NULL
## $ axis.line.x.bottom : NULL
## $ axis.line.y : NULL
## $ axis.line.y.left : NULL
## $ axis.line.y.right : NULL
## $ legend.background : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ legend.margin : 'margin' num [1:4] 5.5points 5.5points 5.5points 5.5points
## ..- attr(*, "unit")= int 8
## $ legend.spacing : 'simpleUnit' num 11points
## ..- attr(*, "unit")= int 8
## $ legend.spacing.x : NULL
## $ legend.spacing.y : NULL
## $ legend.key : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ legend.key.size : 'simpleUnit' num 1.2lines
## ..- attr(*, "unit")= int 3
## $ legend.key.height : NULL
## $ legend.key.width : NULL
## $ legend.text :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : 'rel' num 0.8
## ..$ hjust : NULL
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ legend.text.align : NULL
## $ legend.title :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : num 0
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ legend.title.align : NULL
## $ legend.position : chr "right"
## $ legend.direction : NULL
## $ legend.justification : chr "center"
## $ legend.box : NULL
## $ legend.box.just : NULL
## $ legend.box.margin : 'margin' num [1:4] 0cm 0cm 0cm 0cm
## ..- attr(*, "unit")= int 1
## $ legend.box.background : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ legend.box.spacing : 'simpleUnit' num 11points
## ..- attr(*, "unit")= int 8
## $ panel.background : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ panel.border : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ panel.spacing : 'simpleUnit' num 5.5points
## ..- attr(*, "unit")= int 8
## $ panel.spacing.x : NULL
## $ panel.spacing.y : NULL
## $ panel.grid :List of 6
## ..$ colour : chr "grey92"
## ..$ linewidth : NULL
## ..$ linetype : NULL
## ..$ lineend : NULL
## ..$ arrow : logi FALSE
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_line" "element"
## $ panel.grid.major : NULL
## $ panel.grid.minor :List of 6
## ..$ colour : NULL
## ..$ linewidth : 'rel' num 0.5
## ..$ linetype : NULL
## ..$ lineend : NULL
## ..$ arrow : logi FALSE
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_line" "element"
## $ panel.grid.major.x : NULL
## $ panel.grid.major.y : NULL
## $ panel.grid.minor.x : NULL
## $ panel.grid.minor.y : NULL
## $ panel.ontop : logi FALSE
## $ plot.background : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ plot.title :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : 'rel' num 1.2
## ..$ hjust : num 0
## ..$ vjust : num 1
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 5.5points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ plot.title.position : chr "panel"
## $ plot.subtitle :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : num 0
## ..$ vjust : num 1
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 0points 0points 5.5points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ plot.caption :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : 'rel' num 0.8
## ..$ hjust : num 1
## ..$ vjust : num 1
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 5.5points 0points 0points 0points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ plot.caption.position : chr "panel"
## $ plot.tag :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : 'rel' num 1.2
## ..$ hjust : num 0.5
## ..$ vjust : num 0.5
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ plot.tag.position : chr "topleft"
## $ plot.margin : 'margin' num [1:4] 5.5points 5.5points 5.5points 5.5points
## ..- attr(*, "unit")= int 8
## $ strip.background : list()
## ..- attr(*, "class")= chr [1:2] "element_blank" "element"
## $ strip.background.x : NULL
## $ strip.background.y : NULL
## $ strip.clip : chr "inherit"
## $ strip.placement : chr "inside"
## $ strip.text :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : chr "grey10"
## ..$ size : 'rel' num 0.8
## ..$ hjust : NULL
## ..$ vjust : NULL
## ..$ angle : NULL
## ..$ lineheight : NULL
## ..$ margin : 'margin' num [1:4] 4.4points 4.4points 4.4points 4.4points
## .. ..- attr(*, "unit")= int 8
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ strip.text.x : NULL
## $ strip.text.y :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : NULL
## ..$ angle : num -90
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## $ strip.switch.pad.grid : 'simpleUnit' num 2.75points
## ..- attr(*, "unit")= int 8
## $ strip.switch.pad.wrap : 'simpleUnit' num 2.75points
## ..- attr(*, "unit")= int 8
## $ strip.text.y.left :List of 11
## ..$ family : NULL
## ..$ face : NULL
## ..$ colour : NULL
## ..$ size : NULL
## ..$ hjust : NULL
## ..$ vjust : NULL
## ..$ angle : num 90
## ..$ lineheight : NULL
## ..$ margin : NULL
## ..$ debug : NULL
## ..$ inherit.blank: logi TRUE
## ..- attr(*, "class")= chr [1:2] "element_text" "element"
## - attr(*, "class")= chr [1:2] "theme" "gg"
## - attr(*, "complete")= logi TRUE
## - attr(*, "validate")= logi TRUE
Note that color
and fill
depend on
orientation and are put within the main aes
homo |>
ggplot(aes(orientation)) +
geom_bar()
Make barplots of age
for each speaker:
homo |>
ggplot(aes(speaker, age)) +
geom_col()
Fill bars by orientation:
homo |>
ggplot(aes(speaker, age, fill = orientation)) +
geom_col()
The count statistics is use by default here.
homo |>
ggplot() +
geom_bar(aes(age, fill = orientation))
Plot all data in one bar:
homo |>
ggplot() +
geom_bar(aes(x="", fill = orientation), width = 0.2)
homo |>
mutate(age = as.factor(age)) |>
ggplot() +
geom_bar(aes(x="", fill = age), width = 0.2)
NB the width argument of the barplot.
homo |>
mutate(age = as.factor(age)) |>
ggplot() +
geom_bar(aes(x="", fill = age)) +
coord_polar(theta = "y") +
theme_void()
theme_set(theme_bw()) # set black-and-white theme
homo |>
ggplot(aes(orientation, s.duration.ms)) +
geom_boxplot()
homo |>
ggplot(aes(orientation, s.duration.ms)) +
geom_boxplot()+
geom_point()
homo |>
ggplot(aes(orientation, s.duration.ms)) +
geom_violin() +
geom_jitter(width = 0.1)
homo |>
ggplot(aes(x=s.duration.ms, fill=orientation)) +
geom_density(alpha=0.7, position="stack")+
# geom_vline()+
# scale_color_manual(values=c("#999999", "#000000"))+
# scale_color_grey()+
theme_classic()
Другое решение
homo |>
ggplot(aes(x=s.duration.ms, color=orientation)) +
geom_density() +
geom_vline(xintercept = mean(homo$s.duration.ms[homo$orientation=="hetero"]))+
geom_vline(xintercept = mean(homo$s.duration.ms[homo$orientation=="homo"]))
The plot can be stored as a variable. One can recycle it many times with different options. In order to create a pdf file, put the file name
pdf("plot.pdf")
homo |>
ggplot(aes(orientation, s.duration.ms)) +
geom_boxplot() +
geom_jitter(width = 0.2)
dev.off()
## quartz_off_screen
## 2
Jihui Lee. Data Visualization with ggplot2
Raj Kamal Srivastav. DV using R
Heather Harvey. DV for correlation
Кстати, именно функция subset()
вдохновила
Уикхема на создание filter()
.↩︎