RMarkdown — это пакет, который позволяет соединять
текст, исполняемый код и результаты исполнения кода в единый документ.
Это очень полезно для представления данных. На выходе мы можем получить
файлы .html
, .pdf
— в том числе презентации
форматов .html
и .pdf
1 — .docx
,
.pptx
. Более того, можно связать несколько HTML-документов
и получить сайт или книгу. Ну, гениально же!
Мы сосредоточимся на HTML-документах сегодня, потому что это проще всего и, как показывает практика, полезнее всего.
Установка
Если вдруг ещё не, надо поставить R (Win, Mac, Linux) и RStudio.
Устанавливается RMarkdown как обычный пакет:
install.packages("rmarkdown")
Есть ещё пакет, который не обязательно устанавливать сразу, но он нам пригодится, чтобы делать красивое:
install.packages("prettydoc")
Структура документа
- YAML-шапка
- самый обычный текст (как в блокноте) с форматированием от Markdown, расширенным с помощью Pandoc
- блоки кода (в целом, на любом языке программирования)
- формулы в \(\LaTeX\)’e
Чё внутри происходит?
Кратко взглянем на то, как из .rmd
получается
.html
.
- Мы пишем руками
.rmd.
шку (RMarkdown). - Отправляем её пакету
knitr
, который выполняет чанки кода и делаем.md
шку (Markdown). - Дальше
.md
шку берёт Pandoc, который есть конвертер, и делает окончательный файл, который мы пожелали — например,html
ку или.pdf.
ку, призывая \(\LaTeX\).
Первый .rmd
-файл
Как создать .rmd
шку? Надо проследовать по пути
File > New File > RMarkdown...
, оставить все
настройки по умолчанию и жмакнуть OK
.
Возникнет дефолтный .rmd
-файл.
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
plot(pressure)
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
Его можно скомпилировать либо с помощью функции
rmarkdown::render("file.Rmd")
, либо жмакнув кнопку
Knit
вверху текстового редактора.
Если по дороге ничего не сломалось, то должно получиться что-то такое.
Создайте и скомпилируйте дефолтный .rmd
-файл.
Markdown & Pandoc
- Markdown — это универсальный язык разметки, использующийся очень много где.
- Pandoc — конвертер файлов между различными форматами. А ещё он дает немного плюшек для форматирования (индексы, нумерованные примеры, сноски).
Заголовки
Обозначаются хэштегами, после которых надо обязательно поставить пробел, иначе получится ссылка.
# Заголовок 1
## Заголовок 2
### Заголовок 3
#### Заголовок 4
##### Заголовок 5
###### Заголовок 6
На заголовках можно оставлять теги — они не отображаются — чтобы организовывать навигацию по документу:
# Заголовок 1 {#tag1}
## Заголовок 2 {#header2}
### Заголовок 3 {#wow_third_level_header}
Форматирование
- Курсив / наклон —
*курсив* или _курсив_
- Полужирный —
**полужирный** или __полужирный__
Зачеркнутый—~~зачеркнутый~~
Индексы
- Нижние индексы — CH3CH2OH — в тильдах —
CH~2~CH~3~OH
- Верхние индексы — К+,
Cr2O72- — в шапочках —
К^+^, Cr~2~O~7~^2-^
Списки
Есть несколько вариантов и все рабочие:
Ненумерованные списки
* овощи
* томаты
* все остальные
* фрукты
* обыкновенные
* яблоко
* груша
* тропические
* папайя
* маракуйя
* ягоды
* удобные для сбора
* крыжовник
- овощи
- томаты
- все остальные
- фрукты
- обыкновенные
- яблоко
- груша
- тропические
- папайя
- маракуйя
- обыкновенные
- ягоды
- удобные для сбора
- крыжовник
Ещё можно плюсами и минусами пользоваться, типа вот так
- овощи
+ томаты
+ все остальные
- фрукты
+ обыкновенные
- яблоко
- груша
+ тропические
- папайя
- маракуйя
- ягоды
- удобные для сбора
- крыжовник
- овощи
- томаты
- все остальные
- фрукты
- обыкновенные
- яблоко
- груша
- тропические
- папайя
- маракуйя
- обыкновенные
- ягоды
- удобные для сбора
- крыжовник
Нумерованные списки
1. рыба
1. карп
3. треска
2. камбала
2. мясо
1. всякое
2. разное
3. ни рыба ни мясо
1. птица
1. кура
4. перепёлка
2. инопланетное непонятно что
- рыба
- карп
- треска
- камбала
- мясо
- всякое
- разное
- ни рыба ни мясо
- птица
- кура
- перепёлка
- инопланетное непонятно что
- птица
Смотрите, даже если мы накосячили в нумерации, при компиляции всё поправилось, и нумерация в итоговом доке верная.
Нумерованные примеры
В списки можно собирать некоторые примеры:
(@) Парменид сказал, что «бытие есть --- небытия нет». Трудно поспорить.
(@socrates) Сократ заявил, что он «знает, что ничего не знает, но другие не знают даже этого». Ну, ок.
(@plato) Платон задвигал про мир идей.
(@aristotle) Аристотель нам основал все науки.
- Парменид сказал, что «бытие есть — небытия нет». Трудно поспорить.
- Сократ заявил, что он «знает, что ничего не знает, но другие не знают даже этого». Ну, ок.
- Платон задвигал про мир идей.
- Аристотель нам основал все науки.
Во-вервых, они будут автоматически нумероваться, а во-вторых, если к
ним приписать лейблы (здесь: socrates
, plato
,
arislotle
). Можно будет ссылаться на примеры:
Считается, что (@plato) записывал за (@socrates).
Считается, что (3) записывал за (2).
Ссылки
Вариантов есть несколько и вот они, пожалуй, все.
Вставляем [ссылку](https://www.google.com/) красиво.
Или не очень красиво, но зато ясно, куда она ведет: <https://www.google.com/>.
Если хочется собрать все ссылки в одном месте, то для отображения их в тексте можно оставить [метку][1] или даже просто [метку].
А ещё если у вас есть теги на заголовках, можно ссылаться и внутрь документа, например [так](#tables).
[1]: https://www.google.com/
[метку]: https://yandex.ru/
Вставляем ссылку красиво.
Или не очень красиво, но зато ясно, куда она ведет: https://www.google.com/.
Если хочется собрать все ссылки в одном месте, то для отображения их в тексте можно оставить метку или даже просто метку.
А ещё если у вас есть теги на заголовках, можно ссылаться и внутрь документа, например так.
Картинки
Очень похожи по синтаксису на ссылки, только перед квадратными
скобками надо поставить !
,а внутри них пишется либо ничего,
либо альтернативный
текст/название картинки. В круглых скобках пишется адрес
картинки.


Да, прямо веб-ссылку можно впихнуть туда.
Метки здесь так же работают. ![][cat_shocked]
[cat_shocked]: cat_shocked.png
Метки здесь также работают.
Лично я не большой фанат вставлять картинки средствами Markdown, поэтому использую HTML. Там больше возможностей кастомизации отображения.
Вот так делаю
<center>
<img src="path_to_pic">
</center>
Цитаты
Цитаты оформляются с помощью знака >
:
> Это цитата, которая содержит глубокую философскую мысль.
> Тут мысль раскрывается --- это строка попадает в тот же фрагмент.
> А это уже _следующая_ цитата, в которой применяется __форматирование__.
>
> <p align="right">Автор цитаты</p>
Это цитата, которая содержит глубокую философскую мысль. Тут мысль раскрывается — это строка попадает в тот же фрагмент.
А это уже следующая цитата, в которой применяется форматирование.
Автор цитаты2
Разрыв страницы
Делается тремя звёздочками: ***
. Выглядит так:
Таблицы
Делать руками таблицы — достаточно запарно. В общем-то, не только в Markdown, но и в HTML или \(\LaTeX\) тоже. К тому же, не то чтобы нам очень часто надо делать таблицы руками. Поэтому не будем тратить на это много времени и внимания, и просто сохраним ссылку на генератор таблиц.
Сноски
Делаются так:
Это сноска[^1].
Но лучше не номером, а как-то так[^another_footnote].
[^1]: Да, это сноска.
[^another_footnote]: Да, это тоже сноска, только не по номеру, а через лейбл.
Разницы, где оставлять содержание сноски, особой нет — можно сразу после абзаца, в котором сноска даётся, можно в конце документа.
Я предпочитаю первый вариант, чтобы можно было следовать за содержанием документа и не прыгать по нему, если нужны исправления.
Представим, что вам пора писать статью. Создайте шаблон для неё в RMarkdown.
Шаблон должен содержать:
- заголовки основных разделов
- пара строк текста в каждом разделе, о чем будет этот раздел
- суперважная сноска в каком-нибудь из разделов
- ссылка на какой-то внешний ресурс (например, откуда вы взяли стимульный материал)
- цитата великого ученого, на работы которого вы опираетесь
HTML
Ежели вы монстр и постигли HTML, то можно прям на нём делать вставки в RMarkdown. Ну, скажем, список можно сделать и так:
<ul>
<li>пункт номер раз</li>
<li>пункт номер два</li>
<li>пункт номер три</li>
</ul>
- пункт номер раз
- пункт номер два
- пункт номер три
Кстати, HTML и Markdown можно комбинировать, и это будет работать:
Допустим,
<dl>
<dt>__термин__</dt>
<dd> и его определение, в котором нужно сделать _акцент_, либо <em>акцент</em>.</dd>
</dl>
- термин
- и его определение, в котором нужно сделать акцент, либо акцент.
\(\LaTeX\)
С помощью \(\LaTeX\)’а можно писать красивые формулы. Хорошо, конечно, если вы шарите за \(\LaTeX\), но если нет, можно посмотреть 100500 примеров тут.
Сверхкраткое введение в математику в \(\LaTeX\)’е
- Есть формулы. Они бывают внутритекстовые, которые — шок! — идут внутри текста, и выключные, которые вынесены в отдельную строку.
- Внтуритекстовые формулы оформляются с помощью одинарных знаков
доллара
$ formula $
примерно так:
Если верить тому, что $2 + 2 = 4$, то получается, что $22 + 22 = 44$.
Если верить тому, что \(2 + 2 = 4\), то получается, что \(22 + 22 = 44\).
- Выключные формулы оформляются с помощью двойных знаков доллара
$$ formula $$
. Они всегда выравнены по центру.
Кажется, что если сложить несколько чисел и поделить на их количество, получится нечто, именуемое _средним арифметическим_:
$$
\bar x = \frac{1}{n} \sum_{i=1}^n x_i
$$
Будем думать, что это действительно так.
Кажется, что если сложить несколько чисел и поделить на их количество, получится нечто, именуемое средним арифметическим:
\[ \bar x = \frac{1}{n} \sum_{i=1}^n x_i \]
Будем думать, что это действительно так.
- Есть куча разных операторов-функций типа
\bar
,\sum
,\frac
,\times
и др. Они позволяют вводить всякие разные математические символы. Какие они есть и как их употреблять, можно опять же смотреть тут.
Давайте напишем какую-нибудь формулу в свою статью, что сделать вид, что мы жесть какие умные и что-то понимаем в том, что исследуем. Например, что-то умное про логистическую регрессию:
\[ p_i = \frac{e^{\beta_0 + \sum_{k=1}^p \beta_kx_{ik}}}{1 + e^{\beta_0 + \sum_{k=1}^p \beta_kx_{ik}}} \]
или просто что-то на статистическом про диперсию:
\[ \mathbb{D}(X) = \mathbb{E}(X^2) - \mathbb{E}^2(X) \]
Код
Код заключается в бэктики:
`sum(1, 2, 3)`
. Это если мы хотим код прямо в строке. Если
хотим код отдельным чанком, то по три бэктика в начале и конце:
```
x <- c(1,3,5,7)
mean(x)
```
Правда такие чанки кода не исполняются. Нам такого не надо. Чтобы исполнить код при компиляции файла, надо указать, на каком языке мы написали заклинания.
Языки программирования
Это указывается после первых бэктиков (допустим, мы почему-то пишем на R):
```{r}
x <- c(1,3,5,7)
mean(x)
```
<- c(1,3,5,7)
x mean(x)
## [1] 4
Можно сделать и питон5:
```{python}
spisok = ["where", "is", "my", "beer"]
for word in spisok:
print(word)
```
= ["where", "is", "my", "beer"]
spisok for word in spisok:
print(word)
## where
## is
## my
## beer
Можно вытворить и нечто подобное:
echo "хало ворлд"
## хало ворлд
Если вы совсем странненький, то можно сделать и что-то такое:
#include <Rcpp.h>
// [[Rcpp::export]]
int fibonacci(const int x) {
if (x == 0 || x == 1) return(x);
return (fibonacci(x - 1)) + fibonacci(x - 2);
}
fibonacci(10L)
## [1] 55
Настройка чанков
У чанков достаточно много настроек. Самые важные — echo
,
eval
и include
.
Отображается и код, и аутпут:
```{r}
# Pharmacokinetics of Indomethacin
head(Indometh)
```
Отображается, но *не* исполняется:
```{r, eval=FALSE}
# это я просто покажу, как пакет c гитхаба подгрузить
# полезный пакет, кстати, там есть неплохие шаблоны
devtools::install_github("rstudio/radix")
```
*Не* отображается код, но выводится аутпут:
```{r, echo=FALSE}
print("о боже, как много настроек, я уже забыл, какая первая была")
```
*Не* отображается *ни* код, *ни* аутпут, но чанк исполняется[^include]:
```{r, include=FALSE}
vec <- 1:24
```
[^include]: Параметр `include` в основном используется для задания параметров верстки.
Это значит, что хоть мы и не видим, что вектор создан, мы можем к нему обратиться:
```{r}
vec
```
Отображается и код, и аутпут:
# Pharmacokinetics of Indomethacin
head(Indometh)
## Subject time conc
## 1 1 0.25 1.50
## 2 1 0.50 0.94
## 3 1 0.75 0.78
## 4 1 1.00 0.48
## 5 1 1.25 0.37
## 6 1 2.00 0.19
Отображается, но не исполняется:
# это я просто покажу, как пакет c гитхаба подгрузить
# полезный пакет, кстати, там есть неплохие шаблоны
::install_github("rstudio/radix") devtools
Не отображается код, но выводится аутпут:
## [1] "о боже, как много настроек, я уже забыл, какая первая была"
Не отображается ни код, ни аутпут, но чанк исполняется6:
Это значит, что хоть мы и не видим, что вектор создан, мы можем к нему обратиться:
vec
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Если и другие аргументы, их много. Кратко перечислю самые полезные:
error
— отображать ли ошибки исполнения:- если
FALSE
, то верстка ломается на чанке, который не может выполниться - если
TRUE
, то верстка не ломается, а ошибка отображается в итоговом файле
- если
warning
— отображать ли предупрежденияmessage
— отображать ли сообщения (например, при подключении пакетов)comment
— по дефолту результат работы кода предваряется знаком##
- чтобы его не было, надо прописать
NA
- чтобы его не было, надо прописать
cache
— кэшировать ли результат работы фрагмента кода- Полезная фича, когда вы работаете с какими-либо сложными или большими операциями, занимающими много времени. Если результата закэшировн, он не будет пересчитываться при новой компиляции — значит, будет тратиться меньше времени.
Именование чанков
Каждому чанку можно дать собственное имя (без пробелов и точек внутри имени). Оно указывается после языка:
```{r my_super_fancy_graph}
library(tidyverse)
theme_set(theme_bw())
diamonds %>%
ggplot(aes(price)) +
geom_histogram(data = diamonds %>% select(-color), fill="lightgray") +
geom_histogram(aes(fill = color)) +
facet_wrap(~ color)
```
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.3 ✓ purrr 0.3.4
## ✓ tibble 3.0.4 ✓ dplyr 1.0.2
## ✓ tidyr 1.1.2 ✓ stringr 1.4.0
## ✓ readr 1.4.0 ✓ forcats 0.5.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
theme_set(theme_bw())
%>%
diamonds ggplot(aes(price)) +
geom_histogram(data = diamonds %>% select(-color), fill="lightgray") +
geom_histogram(aes(fill = color)) +
facet_wrap(~ color)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
В целом, этого можно и не делать, однако есть несколько причин этого делать:
- проще читать код
- проще ориентироваться в том, что вы написали год назад
- в случае ошибок при компиляции будет отображаться имя чанка, а не номер
- если чанк закэширован, при добавлении нового перед ним не надо все опять пересчитывать
- можно ссылаться в
blogdown
- при верстке книг в
bookdown
вы избежите косяков по типу того, что на картинке
Возьмите какой-либо встроенный датасет
(library(help = "datasets")
) и напишите код, который:
- выведет описательные статистики по какой-то количественной переменной
- визуализирует её распределение
YAML-шапка
Это то, что находится вверху документа и содержит какие-то метаданные о вашем файле. Например, вот
---
title: "RMarkdown: верстаем красивое"
author: "Антон Ангельгардт"
date: "31.08.202"
output:
prettydoc::html_pretty:
theme: architect
highlight: github
toc: yes
toc_depth: 3
css: "style.css"
---
Тип аутпута
Пожалуй, самое важное. Есть несколько вариантов:
output: html_document
— это настроено по умолчаниюoutput: word_document
output: pdf_document
(придется подружить с \(\LaTeX\)ом на вашем компе)output: ioslides_presentation
output: slidy_presentation
output: slidy_presentation
output: beamer_presentation
и т.д., и т. п., и пр., и др.
Библиография
Здесь мы упомянем BibTeX
, который вообще-то хорошо
дружит с \(\LaTeX\), но сюда прикрепить
тоже можно. Это не единственный способ, но, наверное, самый
универсальный.
- Создаем файл
.bib
со всей библиографией. GoogleScholar генерирует ссылки в форматеBibTeX
автоматически.
@book{xie2016bookdown,
title={Bookdown: Authoring books and technical documents with R markdown},
author={Xie, Yihui},
year={2016},
publisher={Chapman and Hall/CRC}
}
@book{xie2017blogdown,
title={Blogdown: creating websites with R markdown},
author={Xie, Yihui and Thomas, Amber and Hill, Alison Presmanes},
year={2017},
publisher={Chapman and Hall/CRC}
}
- Прописываем в шапке, какой файл отвечает за библиографию:
bibliography: references.bib
- Используем ссылки в тексте, как вот тут
* `bookdown` --- [расширение RMarkdown](https://bookdown.org/yihui/bookdown/) для написания книг, диссера, создания перезентаций и т.д. (@xie2016bookdown)
* `blogdown` --- сайты [можно пилить](https://bookdown.org/yihui/blogdown/) (@xie2017blogdown)
- Список литературы сам формируется в конце.
Оглавление
Есть несколько атрибутов, которые позволяют задать оформление оглавления:
toc
— вставлять ли оглавление финальный докtoc_depth
— сколько уровней иерархии отображать в оглавленииtoc_float
— должно ли оглавление все время следовать за текстомcollapsed
— должно ли оглавление быть все время полностью раскрытоnumber_sections
— автоматическая нумерация секцийcode_folding (hide)
— делать ли кнопочку, показывающую/скрывающую весь код
Отображение датафреймов
Мы уже выше видели, что будет, если попытаться вывести датафрейм — что-то такое:
head(diamonds)
## # A tibble: 6 x 10
## carat cut color clarity depth table price x y z
## <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
## 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43
## 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31
## 3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
## 4 0.290 Premium I VS2 62.4 58 334 4.2 4.23 2.63
## 5 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
## 6 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48
Некрасиво.
Надо, чтобы было красиво.
Для этого есть удобненькая функция kable()
в пакете
knitr
. Во-первых, она сделаем красивое сама, во-вторых, там
можно переименовать колонки — а это важно, ибо переменные в датасете
обычно не то чтобы очень понятно и понимабельно называются.
head(diamonds) %>%
kable(col.names=str_to_title(colnames(.)))
Carat | Cut | Color | Clarity | Depth | Table | Price | X | Y | Z |
---|---|---|---|---|---|---|---|---|---|
0.23 | Ideal | E | SI2 | 61.5 | 55 | 326 | 3.95 | 3.98 | 2.43 |
0.21 | Premium | E | SI1 | 59.8 | 61 | 326 | 3.89 | 3.84 | 2.31 |
0.23 | Good | E | VS1 | 56.9 | 65 | 327 | 4.05 | 4.07 | 2.31 |
0.29 | Premium | I | VS2 | 62.4 | 58 | 334 | 4.20 | 4.23 | 2.63 |
0.31 | Good | J | SI2 | 63.3 | 58 | 335 | 4.34 | 4.35 | 2.75 |
0.24 | Very Good | J | VVS2 | 62.8 | 57 | 336 | 3.94 | 3.96 | 2.48 |
Давайте
- добавим оглавнение в нашу статью
- покажем, как выглядели данные (то есть, отобразим часть датафрейма, по которому считали описательные статистики, красиво.)
Дизигн
CSS
Если вы магистр всея Cascading Style Sheets, то можете полностью накастомизировать все, что хотите. Только подключите потом к самому файлу:
css: "style.css"
Макеты с темами
Мы в самом начале установили пакет prettydoc
, который
содержит в себе весьма pretty темы для RMarkdown-документов. Создать
prettydoc
-файл можно так:
File > New File > RMarkdown... > From Template > Lightweight and Pretty Document (HTML)
YAML-шапка генерируется автоматически, что хорошо. Если вам не нравится, какая тема применилась по умолчанию, можно выбрать другую.
theme: architect
Примените какую-нибудь тему из пакета prettydoc
, чтобы
статья стала неистово pretty.
Куда заливать HTML?
В качестве аутпута мы получаем файл .html
, а значит,
чтобы мир его увидел, он должен быть где-то в интернетах. Вариантов
несколько:
- вы завели собственный хост и живете прекрасно
- вы завели GitHub и включили GitHub Pages и живете не менее прекрасно
- вы пользуетесь бесплатным хостингом Rpubs
Что ещё?
Представление данных, конечно, не ограничивается RMarkdown. Вот некоторые штуки, которые также могут быть полезны:
bookdown
— расширение RMarkdown для написания книг, диссера, создания перезентаций и т.д. (Xie (2016))shiny
— динамические сайты, на которых можно развернуть взамодействие с пользователемflexdashboard
— динамические дэшбордыposterdown
— постеры в RMarkdownpagedown
— тут много всяких шаблонов примерно для всего (от книги, статьи и резюме до приглашения на свадьбу)blogdown
— сайты можно пилить (Xie, Thomas, and Hill (2017))
Список литературы
Здесь использован HTML-тег
p
для того, чтобы сделать выравнивание имени автора по правому краю. К сожалению, сам Markdown про выравнивание ничего не знает :(↩︎Да, это сноска.↩︎
Да, это тоже сноска, только не по номеру, а через лейбл.↩︎
Чтобы оно поехало, нало будет создать чанк, в котором подгружается пакет
reticulate
(стандартно, черезlibrary(reticulate)
) и указывается, какой питон использовать при исполнении кода черезuse_python("path_to_python")
. Путь к питону можно узнать через командную строку с помощьюwhich python3
.↩︎Параметр
include
в основном используется для задания параметров верстки.↩︎