May 11, 2025

Визуализации при помощи Shiny

Оглавление

Основная информация о Shiny

Shiny — это веб-фреймворк для разработки веб-приложений, изначально на R, а с 2022 года на Python. Это мощный инструмент для визуализации данных, анализа и обмена результатами с широкой аудиторией.

Документация

Основные компоненты Shiny

  • Реактивность. Когда пользователь изменяет элемент управления (например, слайдер, поле ввода), Shiny автоматически пересчитывает результаты и обновляет выходные данные (например, графики, таблицы). Это создает отзывчивый и динамичный пользовательский интерфейс.
  • UI (User Interface). Определяет визуальную структуру приложения. Он включает в себя элементы управления (виджеты) для ввода данных и элементы для отображения выходных данных, которые и обеспечивают реактивность запускаемых приложений.
  • Server. Содержит логику приложения. Здесь происходит вся тяжелая работа: обработка данных, выполнение расчетов, создание графиков и таблиц.

Применение Shiny

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

Установка Shiny

Использование на R

Перейти по ссылке и скачать установщик языка R: https://cran.rstudio.com/bin/windows/base/. После запуска установщика можно выбрать предпочитаемый язык и корневую директорию языка, после чего установить его.

Со станицы установки RStudio скачать его установщик:
https://posit.co/download/rstudio-desktop/. После его загрузки также можно выбрать корневую директорию утилиты.

Установка Shiny возможна либо через консоль, либо с помощью интерфейса среды. В первом случае необходимо открыть консоль (Console) и установить пакет:

install.packages("shiny")

Второй способ: при указании библиотеки Shiny в коде приложения RStudio сам предложит установить необходимые зависимости.

Использование на Python

pip install --upgrade pip wheel           # обновление утановщика пакетов
pip install shiny                         # установка библиотеки
pip install --upgrade shiny htmltools     # или её обновление

Онлайн редактор

Помимо локальной разработки своих приложений Shiny имеет официальный онлайн редактор, который позволяет писать код приложения Shiny на R прямо в браузере и наблюдать изменения в реальном времени.

Исходный пример в онлайн редакторе Shiny

Элементы приложения Shiny

После установки всех инструментов становится возможным создание визуализаций на Shiny. Для использования библиотеки в файле с расширением .R:

library(shiny)

Приложение Shiny создаётся вызовом функции shinyApp:

shinyApp(ui = ui, server = server)

В ней указываются 2 основных элемента:

  • ui - пользовательский интерфейс, определяющий инструменты ввода данных и параметров, вывода текста или визуализаций, фильтры. Все эти функции генерируют HTML-разметку.
  • server - логика приложения, обрабатывающая передаваемые интерфейсом данные и производящая рендер графиков.

UI

Разметку макета можно задавать несколькими функциями, которые будут задавать вёрстку и расположение её дочерних элементов. Вот основные из них:

  • fluidPage: создает макет, который масштабируется в зависимости от размера окна браузера. Рекомендуется для большинства приложений. Он использует систему сеток Bootstrap.
  • fixedPage: создает макет фиксированной ширины.
  • sidebarLayout: создает макет с боковой панелью и основной панелью. Принимает два аргумента: sidebarPanel и mainPanel.
  • Другие макеты: fillPage, splitLayout, verticalLayout .

Элементы управления ввода (input widgets) позволяют пользователям вводить данные или взаимодействовать с приложением:

  • textInput - текстовое поле для ввода текста.
  • numericInput - числовое поле для ввода чисел.
  • sliderInput - слайдер для выбора числового значения.
  • selectInput - выпадающий список для выбора из списка вариантов.
  • radioButtons - радиокнопки для выбора одного варианта из списка.
  • checkboxGroupInput - набор флажков для выбора нескольких вариантов из списка.
  • checkboxInput - одиночный флажок (логическое значение).
  • dateInput - выбор даты.
  • dateRangeInput - выбор диапазона дат.
  • fileInput - загрузка файла.
  • actionButton - кнопка.

Элементы вывода (output elements) отображают результаты в приложении. Связываются с Server через output$ переменную. Примеры:

  • plotOutput - место для отображения графика.
  • tableOutput - место для отображения таблицы.
  • dataTableOutput - место для отображения интерактивной таблицы данных.

Server

Server содержит логику приложения. Он получает входные данные от UI (input), выполняет расчеты и рендерит выходные данные для отображения в UI (output). server в коде - это R-фукнция, имеющая 2 параметра:

server <- function(input, output) {
     // Логика обработки данных
}

Функции рендеринга (rendering functions) преобразуют результаты R-кода в формат, который можно отобразить в UI. Они всегда должны быть внутри функции server.

  • renderPlot: рендерит график, созданный с использованием функций plot(), ggplot2 и т.д. Возвращает графический объект.
  • renderTable: рендерит таблицу данных (например, data.frame). Возвращает таблицу.
  • renderDataTable: рендерит интерактивную таблицу данных с возможностью сортировки, фильтрации и постраничной навигации (требует пакет DT). Возвращает таблицу.
  • renderText: рендерит текстовую строку. Возвращает строку.
  • renderPrint: рендерит вывод R-кода. Возвращает результат, который можно распечатать в консоли.
  • renderUI: рендерит UI-элементы. Используется для динамического создания UI. Возвращает HTML-код для элемента UI.
  • renderImage: рендерит изображение. Возвращает список, содержащий информацию об изображении (путь, mime-тип, ширина, высота).

Пример на датасете "Породы собак"

Далее будет разобран простой пример приложения Shiny с 2 визуализациями, построенными на датасете "Породы собак", а также развёрнутом в сервисе shinyapps.io.

Внешний вид получившегося приложения

Объяснение примера

Сперва, подключаются библиотеки:

library(shiny)     # Сама Shiny
library(readr)     # Библиотека для чтения датасета из файла CSV

Затем читается датасет из файла, добавляются вычисляемые поля и устанавливаются константы:

dogsData <- read_csv("dogs.csv")  # Чтение датасета из файла в той же директории, что и приложение
customFields <- c("Вес", "Рост", "Продолжительность жизни", "Стоимость")
for (field in customFields) {
  fieldMin <- paste0(field, " мин")
  fieldMax <- paste0(field, " макс")
  dogsData[field] <- (dogsData[fieldMin] + dogsData[fieldMax]) / 2  # Добавление поля из списка customFields как среднее между 2 соответствующими полями
}
dogsData[["Итоговый рейтинг"]] <- dogsData[["Рейтинг"]] - dogsData[["Антирейтинг"]]  # Вычисление поля итогового рейтинга

DOGS_TOP_DEFAULT <- 10

ui содержит разметку окна, основанную на функции fluidPage. Здесь задаётся название приложения (titlePanel), а также две визуализации, каждая из которых состоит из панели ввода (sidebarPanel) и главной панели с визуализацией (mainPanel):

ui <- fluidPage(
  titlePanel("Породы собак"),
  sidebarLayout(   # Контейнер точечного графика
    sidebarPanel(
      # выпадающие списки с ранее заданными кастомными полями в customFields
      selectInput("paramX", "Ось X:", choices = customFields, selected = customFields[1]),
      selectInput("paramY", "Ось Y:", choices = customFields, selected = customFields[2]),
      selectInput("paramSize", "Размер точек:", choices = customFields, selected = customFields[3]),
    ),
    mainPanel(
      plotOutput("scatterplot")  # тег, заменяемый в server на график (plot)
    )
  ),
  sidebarLayout(   # Контейнер столбчатой диаграммы
    sidebarPanel(
      numericInput("dogsTopCount", "Сколько пород в топе:", min = 3, max = 20, value = DOGS_TOP_DEFAULT),  # поле ввода целого числа
    ),
    mainPanel(
      plotOutput("barplot")  # такой же тег графика, но с другим id
    )
  )
)

Компонент server задаётся как функция с ссылками на объекты input и output. Через input передаются фильтры и параметры, меняющиеся в разметке ui, а в output - ссылки на объекты plotOutput.

В компоненте server отдельно обрабатываются два plotOutput. В первой части рисуется точечный график, ось X, ось Y и размер точек которого зависит от выбранных в разметке полей в выпадающих списках:

output$scatterplot <- renderPlot({  # Ссылке scatterplot из output присваивается реактивный элемент
    # Далее поле, выбранное для отображения меняюегося размера точек, нормализуется в диапазоне [1; 5]
    size_data <- dogsData[[input$paramSize]]
    min_size <- min(dogsData[[input$paramSize]], na.rm = TRUE)
    max_size <- max(dogsData[[input$paramSize]], na.rm = TRUE)
    cex_values <- (size_data - min_size) / (max_size - min_size) * 4 + 1
    
    # Объявление самого точечного графика
    plot(dogsData[[input$paramX]],   # Испольуются значения по полю input$paramX
         dogsData[[input$paramY]],   # Испольуются значения по полю input$paramY
         xlab = input$paramX, ylab = input$paramY,  # Меняются подписи осей
         cex = cex_values,  # Устанавливаются нормализованные значения размера точек
         pch = 21,          # Фигура точки - заполненная точка
         col = "black",     # Цвет границы
         bg = "blue",       # Цвет заполнения
         main = "Диаграмма рассеивания по средним показателям")  # Название графика
  })

Столбчатая диаграмма строится на основе ранее вычисленного поля "Итоговый рейтинг":

output$barplot <- renderPlot({
    dogsTopCount <- reactive({     # Переменная, хранящее количество отображаемых пород в топе
      num <- input$dogsTopCount
      if (is.na(num)) {            # Если поле в интерфейсе не заполнено, присваивается значение по умолчанию
        num <- DOGS_TOP_DEFAULT
      }
      return(num)
    })
    
    # Далее данные агрегируются по породе для правильной обработки
    agg_data <- aggregate(dogsData[["Итоговый рейтинг"]],
                          by = list(Порода = dogsData[["Порода собак"]]),
                          FUN = mean,
                          na.rm = TRUE)
    names(agg_data) <- c("Порода", "СреднийРейтинг")
    # Берутся только первые dogsTopCount пород
    topDogs <- head(agg_data[order(agg_data$СреднийРейтинг, decreasing = TRUE), ], dogsTopCount())
    topDogs <- topDogs[nrow(topDogs):1, ]
    
    # Изменение отступов графика
    par(mar = c(5, 12, 4, 2) + 0.1)
    
    barplot(topDogs$СреднийРейтинг,          # Значения - рейтинг породы
            names.arg = topDogs$Порода,      # Подписи столбцов
            horiz = TRUE,                    # Горизонтальная ориентация
            xlab = "Итоговый рейтинг",       # Подпись для оси X
            main = paste0("Топ-", dogsTopCount(), " пород"),   # Адаптивное название графика
            col = "blue",
            border = "black",
            las = 2)                         # Подписи пород горизонтальны
  })

Запуск приложения:

shinyApp(ui = ui, server = server)

Развёртывание на shinyapps.io

1. Установить библиотеку в консоли RStudio:

install.packages("rsconnect")

2. Авторизоваться на shinyapps.io.

3. Получить токен: перейти в раздел Account -> Tokens:

Блок с токеном shinyapps.io

4. При нажатии на кнопку Show можно будет скопировать строку подключения приложения Shiny к учётной записи:

Строка подключения приложения Shiny к shinyapps.io

5. Вставить в консоль RStudio скопированную строку подключения и выполнить.

6. Развернуть приложение с помощью консольной команды. Укажите полный путь к директории приложения, на Windows также экранируйте символы '\'. В этой директории должен находится app.R с полным кодом приложения, а также вспомогательный файл (для примера выше это dogs.csv):

rsconnect::deployApp("path\\to\\your\\app")

По завершении развёртывания приложение отобразится на shinyapps.io и будет доступно для просмотра и взаимодействия.

Подведение итогов

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

  • Использование в веб-визуализациях. Возможность браузерной реализации без знания HTML, CSS или JavaScript, и с использованием инструментария R.
  • Разнообразие виджетов и шаблонов. Достаточно обширный выбор UI элементов.
  • Возможность глубокой настройки внешнего вида.
  • Бесплатное размещение на shinyapps.io.

Недостатки

  • Использование непопулярного R.
  • Плохая производительность языка R.
  • Невозможность или большая сложность постройки сложных UI.