42  Информационные панели с R Markdown

На этой странице мы рассматриваем основные варианты применения пакета flexdashboard. Этот пакет позволяет вам легко форматировать выходные данные R Markdown в виде информационной панели со вкладками и страницами. Содержимым информационной панели может быть текст, статические рисунки/таблицы или интерактивная графика.

Преимущества flexdashboard:

Недостатки flexdashboard:

Очень подробные самоучители по использованию flexdashboard, информацию из которых мы взяли для этой страницы, можно найти в разделе Ресурсы. Ниже мы опишем ключевые характеристики и приведем пример подготовки информационной панели для изучения вспышки, используя данные о случаях из linelist.

42.1 Подготовка

Загрузка пакета

В данном руководстве мы подчеркиваем использование p_load() из пакета pacman, которая устанавливает подход, если необходимо, и загружает его для использования. Вы можете также установить пакеты с помощью library() из базового R. См. страницу [Основы R] для получения дополнительной информации о пакетах R.

pacman::p_load(
  rio,             # импорт/экспорт данных     
  here,            # путь к файлу
  tidyverse,       # управление данными и визуализация
  flexdashboard,   # версии отчетов R Markdown виде информационных панелей
  shiny,           # интерактивные рисунки
  plotly           # интерактивные рисунки
)

Импорт данных

Мы импортируем набор данных о случаях из имитированной эпидемии Эболы. Если вы хотите выполнять действия параллельно, кликните, чтобы скачать “чистый” построчный список (в виде .rds файла). Импортируйте данные с помощью функции import() из пакета rio (она работает с разными файлами, такими как .xlsx, .csv, .rds - см. детали на странице [Импорт и экспорт]).

# импортируем построчный список
linelist <- import("linelist_cleaned.rds")

Первые 50 строк построчного списка отображены ниже.

42.2 Создание нового R Markdown

После того, как вы установили пакет, создайте новый файл R Markdown, кликнув на File > New file > R Markdown.

В открывшемся окне выберите “From Template” (из шаблона) и выберите шаблон “Flex Dashboard”. Затем вас попросят дать название документу. В примере для этой страницы мы назовем R Markdown “outbreak_dashboard.Rmd”.

42.3 Скрипт

Скрипт - это скрипт R Markdown, поэтому в нем будут те же компоненты и структура, как описано на странице [Отчеты с помощью R Markdown]. Мы кратко вернемся к этому вопросу и подчеркнем отличия от других форматов выходных результатов R Markdown.

YAML

В верхней части скрипта есть заголовок “YAML”. Он начинается с трех дефисов --- и закрываться тоже должен тремя дефисами ---. Параметры YAML указаны в парах key:value (ключ:значение). Отступ и размещение двоеточий в YAML очень важно - пары key:value отделяются двоеточием (а не знаком равно!).

YAML должен начинаться с метаданных для документа. Порядок этих первичных параметров YAML (без отступов) не важен. Например:

title: "My document"
author: "Me"
date: "`r Sys.Date()`"

Вы можете использовать код R в значениях YAML, разместив его как код в строке (перед которым есть r внутри одинарных обратных кавычек), но еще и в кавычках (см. выше в пункте Date).

Требуемый параметр YAML - output:, который уточняет тип файла, который должен быть создан (например, html_document, pdf_document, word_document, либо powerpoint_presentation). Для flexdashboard значение этого параметра чуть запутывает - оно должно быть установлено как output:flexdashboard::flex_dashboard. Обратите внимание на одинарное и двойное двоеточие и нижнее подчеркивание. За этим выходным параметром YAML часто идет дополнительное двоеточие и суб-параметры с отступом (см. параметры orientation: и vertical_layout: ниже).

title: "My dashboard"
author: "Me"
date: "`r Sys.Date()`"
output:
  flexdashboard::flex_dashboard:
    orientation: rows
    vertical_layout: scroll

Как показано выше, отступы (2 пробела) используются для суб-параметров. В таком случае, не забывайте поставить дополнительное двоеточие после первичных, например key:value:.

Если возможно, логические значения следует показывать в YAML строчными буквами (true, false, null). Если двоеточие входит в ваше значение (например, в заголовке), разместите значение в кавычках. См. примеры в разделах ниже.

Фрагменты кода

В скрипте R Markdown может содержаться несколько “фрагментов” кода - это области скрипта, где вы можете записать несколько строк кода R, они функционируют как мини скрипты R.

Фрагменты кода создаются с помощью трех обратных одинарных кавычек и фигурных скобок, в которых внутри напечатана строчная “r”. Фрагмент закрывается тремя обратными одинарными кавычками. Вы можете создать новый фрагмент, напечатав его самостоятельно, используя горячие клавиши “Ctrl + Alt + i” (или Cmd + Shift + r для Mac), либо кликнув на зеленую иконку ‘insert a new code chunk’ (вставить новый фрагмент кода) наверху редактора скрипта. Многие примеры приведены ниже.

Текстовая часть

За пределами “фрагментов” кода R вы можете писать текстовую часть. Как указано на странице [Отчеты с помощью R Markdown], вы можете превратить текст в курсив, поставив вокруг него одну звездочку (*), либо сделать его жирным, окружив двумя звездочками (**). Помните, что маркированные и нумерованные списки чувствительны к новым строкам, отступам и окончанию строки двумя пробелами.

Вы можете также вставить код R в строке текста, как описано на странице [Отчеты с помощью R Markdown], окружив код обратными одинарными кавычками и начав команду с “r”: ` 1+1`(см. пример с датами выше).

Заголовки

Разные уровни заголовков можно создать с разным количеством символов решетка, как описано на странице [Отчеты с помощью R Markdown].

В flexdashboard первичный заголовок (#) создает “страницу” информационной панели. Заголовки второго уровня (##) создают столбец или строку в зависимости от параметра ориентация orientation: (см. детали ниже). Заголовки третьего уровня (###) создают панели для графиков, рисунков, таблиц, текста и т.п.

# Заголовок первого уровня(страница)

## Заголовок второго уровня (строка или столбец)  

### Заголовок третьего уровня (панель для графиков, рисунков и т.п.)

42.4 Атрибуты раздела

В обычном R markdown вы можете уточнить атрибуты, которые будут применены к частям вашей информационной панели, включив опции key=value после заголовка в фигурных скобках { }. Например, в обычном отчете R Markdown в HTML вы можете организовать подзаголовки по вкладкам с помощью ## My heading {.tabset}.

Обратите внимание, что эти атрибуты пишутся после заголовка в текстовой части скрипта. Они отличаются от опций knitr, вставляемых внутри в верхней части фрагментов кода R, например, out.height =.

Атрибуты раздела, специфичные для flexdashboard, включают:

  • {data-orientation=} Установите на rows (строки) или columns (столбцы). Если на вашей информационной панели несколько страниц, добавьте этот атрибут к каждой странице, чтобы указать ориентацию (дополнительно объясняется в разделе макет).
  • {data-width=} и {data-height=} устанавливает относительный размер графиков, столбцов, строк, находящихся в одной плоскости (горизонтальной или вертикальной). Абсолютные размеры скорректированы так, чтобы наилучшим образом заполняют пространство или дисплей устройства благодаря flexbox.
    • Высота графиков тоже зависит от того, зададите ли вы параметр YAML как vertical_layout: fill или vertical_layout: scroll. Если установить на scroll (пролистывание), высота рисунка будет отражать традиционную опцию fig.height = во фрагменте кода R.
    • См. полную документацию по размерам на веб-сайте flexdashboard
  • {.hidden} Используйте, чтобы исключить конкретную страницу из панели навигации
  • {data-navbar=} Используйте для заголовка на уровне страницы, чтобы разместить его внутри выпадающего меню навигационной панели. Задайте имя (в кавычках) выпадающего меню. См. пример ниже.

42.5 Макет

Скорректируйте макет вашей информационной панели следующим образом:

  • Все страницы, столбцы/строки и графики с заголовками R Markdown (например, #, ##, или ###)
  • Скорректируйте параметр YAML ориентация orientation: на rows (строки) или columns (столбцы)
  • Уточните, заполняет ли макет браузер или допускается пролистывание
  • Добавьте вкладки в заголовок конкретного раздела

Страницы

Заголовки первого уровня (#) в R Markdown будут представлять “страницы” информационной панели. По умолчанию страницы появятся в навигационной панели наверху информационной панели.

Вы можете сгруппировать страницы в “меню” внутри навигационной панели, добавив атрибут {data-navmenu=} к заголовку страницы. Будьте осторожны - не включайте пробелы вокруг знака равно, иначе не сработает!

Вот что создаст скрипт:

Вы можете также конвертировать страницу или столбец в “боковую панель” слева стандартной информационной панели, добавив атрибут {.sidebar}. Она может содержать текст (просматриваемый с любой страницы), либо если вы интегрировали интерактивность shiny, она может содержать полезные контроли, вводимые пользователем, например слайдеры или выпадающие меню.

Вот что создаст скрипт:

Ориентация

Задайте ориентацию orientation: параметр yaml, который указывает, как следует интерпретировать заголовки второго уровня (##) в R Markdown - либо как столбцы orientation: columns, либо как orientation: rows.

Заголовки второго уровня (##) будут интерпретироваться как новые столбцы или строки на основе этой настройки orientation.

Если вы установите orientation: columns, заголовки второго уровня будут создавать новые столбцы информационной панели. На информационной панели ниже имеется одна страница, содержащая два столбца, итого три панели. Вы можете откорректироваьт эту относительную ширину столбцов с помощью {data-width=}, как показано ниже.

Вот что создаст скрипт:

Если вы установите orientation: rows, заголовки второго уровня будут создавать новые строки, а не столбцы. Ниже находится тот же скрипт, что и выше, но с orientation: rows, так что заголовки второго уровня создают строки, а не столбцы. Вы можеет скорректировать относительную высоту строк с помощью {data-height=}, как показано ниже.

Вот что создаст скрипт:

Если на вашей информационной панели несколько страниц, вы можете определить ориентацию каждой конкретной страницы, добавив атрибут {data-orientation=} в заголовок каждой страницы (уточните без кавычек rows или columns).

Вкладки

Вы можете разделить содержимое на вкладки с помощью атрибута {.tabset}, как в других выходных HTML в R Markdown.

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

Вы можете сделать то же самое со строками, если вы выбрали ориентацию строк.

Вот что создаст скрипт:

42.6 Добавление содержимого

Давайое начнем строить информационную панель. На нашей простой информационной панели будет 1 страница, 2 столбца и 4 панели. Мы построим панели по элементам для демонстрации.

Вы можете легко включить стандартные выходные результаты R, такие как текст, ggplots и таблицы (см. страницу [Таблицы для презентации]). Просто закодируйте их внутри фрагмента кода R, как вы бы это делали в любом другом скрипте R Markdown.

Примечание: вы можете скачать законченный скрипт Rmd и выходной результат создания информационной панели в HTML - см. страницу [Скачивание руководства и данных].

Текст

Вы можете напечатать в Markdown текст и включить код в строке, как в любом другом выходном файле R Markdown. См. дополнительную информацию на странице [Отчеты с помощью R Markdown].

На этой информационной панели мы включваем сводную текстовую панель, которая включает динамический текст, показывающий последние данные по госпитализациям и количеству случаев, зарегистрированных во вспышке.

Таблицы

Вы можете включить фрагменты кода R, который печает такие выходные данные, как таблицы. Но выходные данные будут лучше выглядеть и реагировать на размер окна, если вы используете функцию kable() из пакета knitr, чтобы отобразить ваши таблицы. Функции flextable могут создать таблицы, которые сокращены/обрезаны.

Например, ниже мы передаем linelist() через команду count(), чтобы создать суммарную таблицу случаев по больнице. В конечном итоге таблица передается в knitr::kable() и результатом будет полоса прокрутки справа. Вы можете больше прочитать об индивидуализации ваших таблиц с помощью kable() или kableExtra тут.

Вот что создаст скрипт:

Если вы хотите показать динамическую таблицу, которая позволяет пользователю фильтровать, сортировать и/или кликать через “страницы” датафрейма, используйте пакет DT и его функцию datatable(), как в коде ниже.

Пример кода ниже показывает, что печатается датафрейм linelist. Вы можете задать rownames = FALSE, чтобы сэкономить горизонтальное пространство, и filter = "top", чтобы поставить фильтры в верхней части каждого столбца. Список других спецификаций можно задать в options =. Ниже мы установим pageLength =, чтобы были видны 5 строк и scrollX =, чтобы пользователь мог использовать полосу прокрутки внизу для горизонтального прокручивания. Аргумент class = 'white-space: nowrap' позволит убедиться, что каждая строка занимает одну линию (не несколько). Вы можете почитать о других возможных аргументах и значениях тут, либо введя ?datatable

DT::datatable(linelist, 
              rownames = FALSE, 
              options = list(pageLength = 5, scrollX = TRUE), 
              class = 'white-space: nowrap' )

Графики

Вы можете распечатать графики на панели информационной панели, как вы это делаете в скрипте R. В нашем примере мы используем пакет incidence2 для создания “эпидкривой” по возрастной группе с помощью двух простых команд (см. страницу [Эпидемические кривые]). Однако, вы можете использовать ggplot() и печатать график тем же образом.

Вот что создаст скрипт:

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

Вы можете также передать стандартный ggplot или другой объект графика в ggplotly() из пакета plotly (см. страницу Интерактивные графики). Это позволит сделать ваш график интерактивным, даст пользователю возможность приближать его, наводить на значение каждой точки данных (в данном случае количество случаев в неделю и возрастная группа на кривой).

age_outbreak <- incidence(linelist, date_onset, "week", groups = age_cat)
plot(age_outbreak, fill = age_cat, col_pal = muted, title = "") %>% 
  plotly::ggplotly()

Вот как это выглядит на информационной панели (gif). Этот интерактивный потенциал все еще будет работать, даже если вы отправите информационную панель по почте как статический файл (не онлайн или на сервере).

Виджеты HTML

Виджеты HTML для R - специальный класс пакетов R, который повышает интерактивность с помощью использования библиотек JavaScript. Вы можете интегрировать их в выходные результаты R Markdown (например, как flexdashboard) и в информационные панели Shiny.

Некоторые частые примеры этих виджетов:

  • Plotly (используется на этой странице руководства и на странице Интерактивные графики)
  • visNetwork (используется в данном руководстве на странице [Цепочки распространения])
  • Leaflet (используется в данном руководстве на странице [Основы GIS])
  • dygraphs (полезен для интерактивной демонстрации данных временных рядов)
  • DT (datatable()) (используется, чтобы показать динамические таблицы с фильтром, сортировкой и т.п.)

Ниже мы демонстрируем добавление к информационной панели цепочки распространения для эпидемии, которая использует visNetwork. Скрипт показывает только новый код, добавляемый к разделу “Column 2” (Столбец 2) скрипта R Markdown. Вы можете найти код на странице руководства [Цепочки распространения].

Вот что создаст скрипт:

42.7 Организация кода

Вы можете решить заложитоь весь код внутри скрипта R Markdown flexdashboard. Альтернативно, чтобы получить более чистый и краткий скрипт информационной панели, вы можете вызывать код/рисунки, которые размещены или созданы во внешних скриптах R. Это более подробно описывается на странице [Отчеты с помощью R Markdown].

42.8 Shiny

Интеграция пакета R shiny может сделать ваши информационные панели еще более реагирующими на действия пользователя. Например, вы можете дать пользователю возможность выбрать юрисдикцию или диапазонтдат и позволить панелям реагировать на этот выбор (например, фильтровать отображаемые данные). Чтобы встроить реагирование shiny в flexdashboard, вам нужно внести всего несколько изменений в ваш скрипт flexdashboard R Markdown.

Вы можете использовать shiny, чтобы создать приложения/информационные панели без flexdashboard. Страница руководства [Информационные панели с Shiny] делает обзор этого подхода, включая образцы синтаксиса shiny, структуру файлов приложения, а также опции предоставления доступа/публикации (включая опцию на бесплатном сервере). Этот синтаксис и общие советы работают и в контексте flexdashboard.

Интеграфиц shiny в flexdashboard однако является фундаментальным изменением вашего flexdashboard. Он больше не будет выдавать выходной результат в HTML, который вы можете отправить по электронной почте и который любой может открыть и просмотреть. Вместо этого, это уже будет “приложением”. Вместо кнопки “Knit” в верхней части скрипта появится иконка “Run document” (выполнить документ), которая откроет интерактивную панель локально на вашем компьютере.

Чтобы поделиться вашей информационной панелью вы теперь должны будете:

  • Отправить скрипт Rmd пользователю, он должен будет открыть R на своем компьютере, выполнить приложение или
  • Приложение/информационная панель размещается на сервере, доступном пользователю

Таким образом существуют преимущества в интеграции shiny, но есть и сложности. Если предоставление панели по электронной почте является для вас приоритетом и вам не нужны возможности shiny, реагирующие на запросы пользователей, рассмотрите возможность снижения интерактивности, предлагаемой ggplotly(), как показано выше.

Ниже мы приводим очень простой пример использования того же файла “outbreak_dashboard.Rmd”, что и выше. Детальная документация по интеграции Shiny в flexdashboard доступна онлайн тут.

Настройки

Включите функционал shiny в flexdashboard, добавив параметр YAML runtime: shiny на том же уровне отступа, что и output:, как ниже:

---
title: "Outbreak dashboard (Shiny demo)"
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
    vertical_layout: fill
runtime: shiny
---

Также удобно включать “боковую панель”, где будут содержаться входные виджеты shiny, которые будут собирать информацию от пользователя. Как объяснялось выше, создайте столбец и укажите опцию {.sidebar}, чтобы создать боковую панель слева. Вы можете добавить текст и фрагменты R, содержащие входные команды shiny input внутри этого столбца.

Если ваше приложение/информационная панель размещены на сервере и могут иметь несколько пользователей одновременно, назовите первый фрагмент кода R global. Включите команды по импорту/загрузке ваших данных в этот фрагмент. Этот специально именованный фрагмент теперь будет восприниматься по-другому, и данные, импортированные в нем, импортируются только один раз (а не постоянно) и доступны всем пользователям. Это улучшит скорость запуска приложения.

Отработанный пример

Здесь мы адаптируем скрипт flexdashboard “outbreak_dashboard.Rmd” для включения shiny. Мы добавим функционал для пользователя по выбору больницы из выпадающего меню, а также сделаем так, чтобы эпидемическая кривая отражала только случаи из этой больницы с динамическим заголовком графика. Мы сделаем следующее:

  • Добавляем runtime: shiny в YAML
  • Переименовываем установочный фрагмент в global
  • Рассмотрите возможность создания боковой панели, содержащей:
    • Код для создания вектора уникальных имен больниц
    • Команду selectInput() (выпадающее меню shiny) с выбором имен больниц. Выбор сохраняется как hospital_choice, на который можно ссылаться в более позднем коде как input$hospital_choice
  • Код эпидемической кривой (столбец 2) обернут в renderPlot({ }), включая:
    • Фильтр по набору данных, ограничивая столбец hospital до текущего значения input$hospital_choice
    • Динамический заголовок графика, который включает input$hospital_choice

Обратите внимание, что любой код, ссылающийся на значение input$, должен быть внутри функции render({}) (чтобы быть реагирующим).

Вот верхняя часть скрипта, включая YAML, глобальный фрагмент и боковую панель:

Вот столбец 2, с реагирующим графиком эпидкривой:

Вот информационная панель:

Другие примеры

Чтобы прочитать пример, связанный с здравоохранением, в flexdashboard, используя интерактив shiny и виджет карт leaflet, см. эту главу онлайн книги Геопространственные медицинские данные: моделирование и визуализация с R-INLA и Shiny.

42.9 Предоставление доступа

Информационные панели, которые не содержат элементы Shiny, будут выданы как файл HTML (.html), который можно отправить по электронной почте (если позволяет размер). Это полезно, так как вы можете скинуть отчет в виде “информационной панели” и не создавать сервер для размещения его, как вебсайта.

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

42.10 Ресурсы

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

https://bookdown.org/yihui/rmarkdown/dashboards.html

https://rmarkdown.rstudio.com/flexdashboard/

https://rmarkdown.rstudio.com/flexdashboard/using.html

https://rmarkdown.rstudio.com/flexdashboard/examples.html