Date Редакция Категория comp Теги R / Shiny / учебник

Перевод-пересказ руководства.

Настало время сделать по настоящему "живое" приложение. Этот урок позволит вам создавать приложения, реагирующие на действия пользователя. Эти реакции автоматически возникают, когда пользователь изменяет состояние того или иного виджета.

К концу этого урока вы будете знать, как сделать простенькое приложение на Shiny с двумя "реактивными" строками текста. Каждая строка будет отображать значения виджета, основываясь на том, какие данные введены пользователем.

paste.png

Для нового приложения потребуется своя собственная папка. Создайте в рабочем каталоге папку с именем census-app. В ней мы будем хранить файлы ui.R и server.R, созданные в ходе этого урока.

Два шага

Задать реакцию приложения можно в два шага:

  1. добавить объект R в пользовательский интерфейс ui.R;
  2. в файле server.R рассказать Shiny о том, как построить объект. Объект будет "реактивным", если его код обращается к значению виджета.

Шаг 1: добавляем объект R в UI

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

Функция вывода создаёт
htmlOutput raw HTML
imageOutput image
plotOutput plot
tableOutput table
textOutput text
uiOutput raw HTML
verbatimTextOutput text

Вы можете добавить функцию вывода в пользовательский интерфейс тем же способом, что HTML-элементы и виджеты. Разместите функцию вывода в боковой панели (sidebarPanel) или главной панели (mainPanel) в файле ui.R.

Например, в файле ui.R, показанном ниже, используется textOutput, чтобы вывести строку текста на главную панель приложения, показанного на рисунке выше.

# ui.R

shinyUI(fluidPage(
  titlePanel("censusVis"),

  sidebarLayout(
    sidebarPanel(
      helpText("Create demographic maps with 
        information from the 2010 US Census."),

      selectInput("var", 
        label = "Choose a variable to display",
        choices = c("Percent White", "Percent Black",
          "Percent Hispanic", "Percent Asian"),
        selected = "Percent White"),

      sliderInput("range", 
        label = "Range of interest:",
        min = 0, max = 100, value = c(0, 100))
    ),

    mainPanel(
      textOutput("text1")
    )
  )
))

Обратите внимание, что аргументом функции textOutput является текстовая строка "text1". Каждая из функций вывода вида *Output принимает на вход один аргумент — текстовую строку, которую Shiny воспринимает как имя "реактивного" элемента. Пользователи вашего приложения этого имени не увидят, но вы сможете использовать его для обращения к этому объекту.

Шаг 2: запишите код, чтобы создать объект

Размещение функции в ui.R говорит Shiny где отобразить ваш объект. Теперь нужно объяснить Shiny как этот объект создать.

Сделайте это, вставив в файл server.R R код, который создаёт объект. Код должен помещаться в безымянной функции, которая находится внутри shinyServer в скрипте server.R.

Безымянная функция играет особую роль в работе Shiny: она строит спископодобный объект с именем output, который содержит весь код, необходимый для обновления объектов R в приложении. Каждый объект R должен иметь свою собственную запись в этом списке.

Вы можете создать такую запись, определяя новый элемент output в безымянной функции, как показано ниже. Имя элемента должно совпадать с именем реактивного элемента, который вы создали в ui.R.

В скрипте показанном ниже? output$text1 соответствует textOutput("text1") в файле ui.R вашего приложения.

# server.R

shinyServer(function(input, output) {

     output$text1 <- renderText({ 
          "You have selected this"
     })

  }
)

В безымянной функции не нужно организовывать возврат результата расчетов в последней строке кода. R будет автоматически обновлять output.

Каждая запись в output должна содержать вывод одной из функций Shiny из семейства render*. Эти функции захватывают выражение R и выполняют его предварительную обработку. Используйте функцию render*, которая соответствует типу используемого вами реактивного объекта.

render*-функция создаёт
renderImage images (saved as a link to a source file)
renderPlot plots
renderPrint any printed output
renderTable data frame, matrix, other table like structures
renderText character strings
renderUI a Shiny tag object or HTML

Каждая функция семейства *render принимает единственный аргумент: выражение R, окруженное фигурными скобками — {}. Выражение может состоять всего из одной строки или же из многих строк кода, как если бы это был вызов сложной функции.

Думайте об этом выражении R как о наборе инструкций, которые вы даете Shiny для хранения — на будущее. Shiny выполнит эти инструкции при первом запуске приложения, а затем будет повторно запускать их на выполнение всякий раз, когда необходимо будет обновить объект.

Для всё это заработало, ваше выражение должно возвращать объект, который вы собираетесь выводить (фрагмент текста, график, набор данных и т. п.). Если выражение не возвращает объект или возвращает неправильный тип объекта, вы получите сообщение об ошибке.

Использование значений виджета

Если вы запустите приведенный выше скрипт server.R, то приложение Shiny отобразит на главной панели: "You have selected this". Однако этот текст не будет "реактивным". Это значит, что он не изменится, как бы вы ни манипулировали виджетами вашего приложения.

Вы можете сделать текст реактивным, указывая Shiny вызывать значение виджета всякий раз, когда он строит текст. Давайте посмотрим, как это можно сделать.

Взгляните на первую строку кода в server.R. Вы заметили, что безымянная функция содержит два аргумента — input и output? Вы уже видели, что output — это спископодобный объект, который хранит инструкции для создания объектов R в вашем приложении.

input — это второй спископодобный объект. Он хранит текущие значения всех виджетов в вашем приложении. Эти значения будут сохранены под именами, которые вы дали виджетам в ui.R.

Так, например, наше приложение содержит два виджета: один называется "Var", второй — "range" (вы дали эти имена виджетам на Уроке 3). Значения "Var" и "range" будут сохранены в input как input$var и input$range. Поскольку виджет ползунка (slider) содержит две переменные (минимум и максимум), input$range будет содержать вектор длины 2.

Shiny автоматически сделает объект реактивным, если тот использует значение из input. Например, в файле server.R ниже строка текста становится реактивной благодаря тому, что для её построения используется значение из списка "var".

# server.R

shinyServer(
  function(input, output) {

    output$text1 <- renderText({ 
      paste("You have selected", input$var)
    })

  }
)

Shiny отслеживает, какие выходы (элементы output) от каких виджетов зависят. Когда пользователь изменяет виджет, Shiny перестраивает все выходы, которые зависят от данного виджета, используя его новое значение. В результате объект перестраивается и всегда отражает текущее значение виджета.

Вот так с помощью Shiny создаются реакции на действия пользователя: вы соединяете значение входа (из input) с объектом на выходе, а Shiny реализует всё остальное.

Запускаем приложение и следим за реакциями

Когда всё будет готово, обновите файлы server.R и ui.R вашего приложения так, чтобы они соответствовали показанным выше. Затем запустите приложение:

runApp("censusVis", display.mode = "showcase") 

Ваше приложение должно выглядеть так, как показано на рисунке ниже и выражение на его панели должно обновляться мгновенно, как только вы измените значение в виджете списка.

Обратите внимание на скрипт server.R. Когда Shiny перестраивает текст на панели, в коде скрипта выделяются строки, которые в данный момент выполняются. Такое выделение работает благодаря опции display.mode = "showcase" и помогает увидеть, как Shiny создает реактивный выход.

paste2.png

Ваша очередь

Добавьте вторую строку реактивного текста в главную панель вашего Shiny-приложения. Эта строка должна содержать "You have chosen a range that goes from something to something", и каждое something должно показывать текущее минимальное (min) и максимальное (max) значение полозка.

Не забудьте обновить ваши файлы ui.R и server.R.

Ответы

# ui.R

shinyUI(fluidPage(
  titlePanel("censusVis"),

  sidebarLayout(
    sidebarPanel(
      helpText("Create demographic maps with 
        information from the 2010 US Census."),

      selectInput("var", 
        label = "Choose a variable to display",
        choices = c("Percent White", "Percent Black",
          "Percent Hispanic", "Percent Asian"),
        selected = "Percent White"),

      sliderInput("range", 
        label = "Range of interest:",
        min = 0, max = 100, value = c(0, 100))
    ),

    mainPanel(
      textOutput("text1"),
      textOutput("text2")
    )
  )
))

И

# server.R

shinyServer(
  function(input, output) {

    output$text1 <- renderText({ 
      paste("You have selected", input$var)
    })

    output$text2 <- renderText({ 
      paste("You have chosen a range that goes from",
        input$range[1], "to", input$range[2])
    })

  }
)

Обсуждение

Вторая строка текста добавляется тем же способом, что и первая. Чтобы разместить вторую строку текста на главной панели (mainPanel), Используйте textOutput в ui.R. А для того, чтобы объяснить Shiny как построить этот текст, используйте renderText в server.R. Вы должны будете использовать одно и то же имя для обозначения текста в обоих файлах (например, “text2").

Ваш текст должен использовать как минимальное, так и максимальное значение полозка, которые сохраняются как input$range[1] и input$range[2] соответственно.

Помните, что ваш текст будет реагировать на изменения всё время пока значения со входа приложения соединены с объектами, реализующими вывод. Shiny создает реакции автоматически, когда находит в коде такие связи.

Резюме

На этом уроке вы создали своё первое реактивное приложение на Shiny. В ходе этого вы научились:

  • использовать функцию *Output в файле ui.R для размещения в приложении реактивных объектов;
  • использовать функцию render* в server.R, чтобы указать Shiny как строить эти объекты;
  • окружать выражения R фигурными скобками {} в каждой функции render*;
  • сохранять выражения render* в списке output, по одному для каждого реактивного объекта вашего приложении;
  • создавать реакции путем включения входных значений в выражения render*.

Если вы будете следовать этим правилам, Shiny автоматически сделает ваши объекты реактивными.

На Уроке 5 вы создадите более продвинутое реактивное приложение, использующее скрипты R и внешние данные.



Комментарии

comments powered by Disqus