- •Федеральное агентство связи
- •Введение
- •Разработка Shiny приложений
- •Структура Shiny приложения
- •Создание пользовательского интерфейса
- •Html контент
- •Изображения
- •Виджеты управления
- •Отображение реакции объектов
- •R скрипты и данные
- •Набор данных counties.Rds
- •Скрипт helpers.R
- •Загрузка файлов и указание путей
- •Завершение построения приложения
- •Использование реактивных выражений
- •Флажки и диапазоны дат
- •Оптимизация вычислений
- •Реактивные выражения
- •Зависимости
- •Оптимизация обслуживания флажка
- •Использование Shiny приложений
- •Контрольные задания
- •Разработка knitr документов Использование пакета knitr
- •Разработка r презентаций
- •Начало разработки
- •Основы формирования слайдов
- •Создание контента
- •Переходы между слайдами и навигация
- •Настройка шрифтов и внешнего вида
- •Контрольные задания
Зависимости
Что произойдет, если пользователь изменяет содержимое виджета тикер акции, т.е. значение переменой symb?
Это сделает график, нарисованный функцией renderPlot() не актуальным, но renderPlot() не будет вызывать input$symb. Тем не менее, Shiny перерисует график, благодаря тому что отслеживает, от какого виджета зависит реактивные выражения объекта вывода. Shiny автоматически заново строит объект, если:
входное значение у объектов из render* функции изменяется;
реактивное выражение у объектов из render* функции устаревает.
Реактивные выражения можно представить, как звенья одной цепи, которые связывают входные и выходные значения объектов. Выходные значения объектов будет реагировать на изменения, внесенные в любом месте ниже по течению в цепочке. (Можете составить длинную цепочку, потому что реактивные выражения могут вызывать другие реактивные выражения).
Реактивные выражения можно вызывать только внутри reactive или render* функции. Потому, что только эти функции способны обслуживать реактивные выходы, которые могут быть изменены без предупреждения.
Оптимизация обслуживания флажка
Приступим к «оживлению» флажка «Адаптация цен с учетом инфляции». Пользователь должен иметь возможность для переключения между ценами с учетом инфляции и не скорректированными ценами.
Функция регулировки в helpers.R использует данные индекса потребительских цен, предусмотренных федеральным резервным банком Сент-Луиса, чтобы преобразовать цены. Посмотрим как ее можно реализовать в приложении. Вот одно из решений, которое не является идеальным:
# server.R
shinyServer(function(input, output) {
dataInput <- reactive({
getSymbols(input$symb, src = "yahoo",
from = input$dates[1],
to = input$dates[2],
auto.assign = FALSE)
})
output$plot <- renderPlot({
data <- dataInput()
if (input$adjust) data <- adjust(dataInput())
chartSeries(data, theme = chartTheme("white"),
type = "line", log.scale = input$log, TA = NULL)
})
})
Функция adjust() вызывается внутри renderPlot(). Если флажок установлен, приложение будет преобразовывать все цены каждый раз.
Устранить эту проблему можно путем добавления нового реактивного выражения. Реактивная выражение должно взять значение dataInput() и вернуть преобразованную или непреобразованную копию данных:
# server.R
shinyServer(function(input, output) {
dataInput <- reactive({
getSymbols(input$symb, src = "yahoo",
from = input$dates[1],
to = input$dates[2],
auto.assign = FALSE)
})
finalInput <- reactive({
if (!input$adjust) return(dataInput())
adjust(dataInput())
})
output$plot <- renderPlot({
chartSeries(finalInput(), theme = chartTheme("white"),
type = "line", log.scale = input$log, TA = NULL)
})
})
Теперь каждый вход выделен в собственном реактивном выражения или render* функции. Если вход изменяется, только устаревшие выражения будет повторно запускать:
Вот пример последовательности работы этого приложения:
устанавливаем флажок «Логарифмическа шкала по Y» ;
renderPlot() перезапускается;
в renderPlot() вызывается finalInput();.
finalInput() проверяет dataInput() и input$adjust;
если ничего ни изменилось, finalInput() возвращает сохраненное значение;
если что-либо изменилось, finalInput() вычисляет новое значение с текущими входами, после чего вычисляется новое значение renderPlot() и сохраняется для будущих запросов.