class: center, middle, inverse, title-slide # Introdução ao Dashboard com Shiny ###
### 2020-06-05 --- class: middle ## Iremos aprender... ### 1. O básico de um Shiny App ### 2. Reatividade ### 3. Layouts (shinydashboard) <img src="img/hex-shiny.png" style="position: fixed; top: 250px; right: 75px; z-index: 1;" width="15%"> --- class: middle ## Dashboards Dinâmicos <img src="img/como-funciona.png"> .footnote[ source: [rstudio.com/shiny/](http://www.rstudio.com/shiny/) ] --- class: middle, center <img src="img/hex-shiny.png" style="position: fixed; top: 50px; left: 75px; z-index: 1;" width="9%"> <img src="img/shiny.png" width = "50%"> <img src="img/shiny2.png" width = "50%"> ### Motivação: ### [Shiny Gallery](https://shiny.rstudio.com/gallery/) ### [Show me Shiny Website](https://www.showmeshiny.com/) --- ## Hello World ```r library(shiny) ui <- fluidPage("Hello World!") server <- function(input, output, session) { } shinyApp(ui, server) ``` --- class: middle, center ## Ao R! <img src="https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif" width = "300" height = "300"> --- ## Inputs e Outputs <img src="img/inputs_outputs.png" width = "500" height = "300"> ```r ui <- fluidPage( # *Input() functions, # *Output() functions ) ``` --- ## Inputs <img src="img/inputs.png", width = "100%"> .footnote[ source: [rstudio.com/shiny/](http://www.rstudio.com/shiny/) ] --- ## Outputs <table> <thead> <tr> <th style="text-align:left;"> Function </th> <th style="text-align:left;"> Output </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> imageOutput() </td> <td style="text-align:left;"> image </td> </tr> <tr> <td style="text-align:left;"> plotOutput() </td> <td style="text-align:left;"> plot </td> </tr> <tr> <td style="text-align:left;"> tableOutput() </td> <td style="text-align:left;"> table </td> </tr> <tr> <td style="text-align:left;"> textOutput() </td> <td style="text-align:left;"> text </td> </tr> <tr> <td style="text-align:left;"> verbatimOutput() </td> <td style="text-align:left;"> text </td> </tr> <tr> <td style="text-align:left;"> htmlOutput() </td> <td style="text-align:left;"> raw HTML </td> </tr> <tr> <td style="text-align:left;"> dataTableOutput() </td> <td style="text-align:left;"> interactive table </td> </tr> <tr> <td style="text-align:left;"> uiOutput() </td> <td style="text-align:left;"> a Shiny UI element </td> </tr> </tbody> </table> --- ## No exemplo "hello world" vamos... 1) inserir um sliderInput que aceita valures de 1 a 100. 2) inserir um plotOutput() 3) inserir um textInput com `inputId = "title"`. (exercício!) --- ## Server ```r server <- function(input, output, session) { } ``` --- ## Server ```r server <- function(input, output, session) { output$hist <- renderPlot({ hist(rnorm(100)) }) } ``` -- Lembrando do nosso UI... ```r ui <- fluidPage( ... plotOutput("hist") ) ``` --- ## Server ### funções **`render*()`** .pull-left[ <table> <thead> <tr> <th style="text-align:left;"> *output() </th> <th style="text-align:left;"> render*() </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> imageOutput() </td> <td style="text-align:left;"> renderImage() </td> </tr> <tr> <td style="text-align:left;"> plotOutput() </td> <td style="text-align:left;"> renderPlot() </td> </tr> <tr> <td style="text-align:left;"> tableOutput() </td> <td style="text-align:left;"> renderTable() </td> </tr> <tr> <td style="text-align:left;"> textOutput() </td> <td style="text-align:left;"> renderText() </td> </tr> <tr> <td style="text-align:left;"> verbatimOutput() </td> <td style="text-align:left;"> renderText() </td> </tr> <tr> <td style="text-align:left;"> htmlOutput() </td> <td style="text-align:left;"> renderUI() </td> </tr> <tr> <td style="text-align:left;"> dataTableOutput() </td> <td style="text-align:left;"> renderDataTable() </td> </tr> <tr> <td style="text-align:left;"> uiOutput() </td> <td style="text-align:left;"> renderUI() </td> </tr> </tbody> </table> ] .pull-right[ ```r # ui plotOutput("hist") ``` ```r # server output$hist <- renderPlot({ hist(rnorm(100)) }) ``` ] --- ## Valores Reativos e Funções Reativas Use valores dos inputs com **`input$`** .pull-left[ <img src="img/inputvalues.png" width= "100%"> ] .pull-right[ <img src="img/sliderinputexample.png" width= "80%"> - `render*()` são **funções reativas** - `input$*` são **valores reativos** ] .footnote[ source: [rstudio.com/shiny/](http://www.rstudio.com/shiny/) ] -- se colocarmos **`input$num`** dentro do **`renderPlot()`** no nosso exemplo, o output irá reagir caso o usuário mexa no slider. ```r # server hist(rnorm(input$num)) ``` --- ## Server ### Recapitulando: Dentro da função `server`, 1) salve o output usando **`output$hist <- render*()`** 2) alimente o output **`render*()`** com código 3) acesse os valores dos inputs com **`input$*`** 4) crie reatividade usando **`input$*`** dentro dos **`render*()`** ```r # server output$hist <- renderPlot({ hist(rnorm(input$num)) }) ``` --- ## Voltando ao nosso exemplo "hello world"... 1) faça o título do histograma depender do textInput que você criou anteriormente. (exercício!) 2) finalmente, crie um **`verbatimTextOutput("summary")`** no ui e o alimente com **`summary(rnorm(input$num))`** usando **`renderPrint({})`** no server. (exercício!) --- class: middle, center, inverse # Reatividade --- ## Reatividade Reatividade é a relação entre **valores reativos** e **funções reativas**: **valores reativos** disparam **funções reativas** <img src="img/reactive1.png" width= "100%"> --- ## Contexto de Reatividade Valores reativos só podem ser usados dentro de **contextos de reatividade**. ### Certo ```r # server * output$hist <- renderPlot({hist(rnorm(input$num))}) ``` ### Errado ```r # server output$hist <- hist(rnorm(input$num)) ``` --- ## Funções Reativas ### Principais funções reativas no Shiny - **`render*({})`** - **`reactive({})`** - **`isolate({})`** - **`observe({})`** - **`eventReactive({})`** - **`oberveEvent({})`** --- ## Funções Reativas ### **`reactive({})`** Constrói uma **expressão reativa** (se comportam como **`input$*`**!). ```r # server data <- reactive({ rnorm(input$num) }) ``` É usado como uma função qualquer do R: ```r # server output$summary <- renderPrint({ summary(data()) }) ``` --- ## Funções Reativas ### **`reactive({})`** <img src="img/reactive2.png" width= "80%"> 1) Exercício: crie uma expressão reativa data() no exemplo 'hello world'. .footnote[ source: [rstudio.com/shiny/](http://www.rstudio.com/shiny/) ] --- ## Funções Reativas ### **`isolate({})`** Transforma um **valor reativo** em um **valor não reativo**. ```r # server output$hist <- renderPlot({ title <- isolate(input$title) hist(data(), main = title) }) ``` Agora o **`renderPlot({})`** NÃO vai reagir se o **`input$title`** mudar. --- ## Funções Reativas ### **`observeEvent({})`** Útil para disparar um bloco de código assim que um certo **`input$*`** mudar. ```r # ui actionButton("write_data", "Write Data as CSV") ``` ```r # server observeEvent(input$write_data, { write.csv(data(), "data.csv") }) ``` PS: actionButton é apenas outro tipo de input! Útil para ser usado com **`observeEvent()`**. Ver [Using Action Button](https://shiny.rstudio.com/articles/action-buttons.html) do Shiny docs. Exercício: coloque a funcionalidade 'write data' no exemplo 'hello world'. --- ## Funções Reativas ### **`observe({})`** Também útil para disparar um bloco de código no servidor, porém qualquer **expressão/valor reativo** dentro dele vai dispará-lo. ```r # server observe({ print(data()) print(as.numeric(input$writ_data)) }) ``` --- ## Funções Reativas ### **`eventReactive({})`** Cria uma **expressão reativa** que responde às mudanças do **`input$*`** dentro dele (ou de qualquer outra **expressão reativa**). ```r # ui actionButton("update", "Update!") ``` ```r # server data <- eventReactive(input$update, { write.csv(data(), "data.csv") }) ``` Exercício: atualize o **`data()`** para um eventReactive no 'hello world'. --- class: middle, center, inverse # Layouts ## [shiny.rstudio.com/layout-guide](https://shiny.rstudio.com/articles/layout-guide.html) --- ## Mas antes... HTML Tags ```r fluidPage( tags$h1("Meu Primeiro Shiny App"), tags$p( "O link para o site do Shiny é ", tags$a(href = "https://www.rstudio.com/shiny/", "rstudio.com/shiny."), tags$strong("Recomendo fortemente que você dê uma olhada!") ) ) ``` ```html <div class="container-fluid"> <h1>Meu Primeiro Shiny App</h1> <p> O link para o site do Shiny é <a href="https://www.rstudio.com/shiny/">rstudio.com/shiny.</a> <strong>Recomendo fortemente que você dê uma olhada!</strong> </p> </div> ``` --- ## Mas antes... HTML Tags ```r names(tags) ``` ``` ## [1] "a" "abbr" "address" "area" "article" ## [6] "aside" "audio" "b" "base" "bdi" ## [11] "bdo" "blockquote" "body" "br" "button" ## [16] "canvas" "caption" "cite" "code" "col" ## [21] "colgroup" "command" "data" "datalist" "dd" ## [26] "del" "details" "dfn" "dialog" "div" ## [31] "dl" "dt" "em" "embed" "eventsource" ## [36] "fieldset" "figcaption" "figure" "footer" "form" ## [41] "h1" "h2" "h3" "h4" "h5" ``` ... ```r tags$h1("Meu Primeiro Shiny App") ## <h1>Meu Primeiro Shiny App</h1> ``` --- ## Mas antes... HTML Tags As tags mais usadas: <table> <thead> <tr> <th style="text-align:left;"> R function </th> <th style="text-align:left;"> HTML </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> a() </td> <td style="text-align:left;"> um hyperlink </td> </tr> <tr> <td style="text-align:left;"> hr() </td> <td style="text-align:left;"> linha horizontal </td> </tr> <tr> <td style="text-align:left;"> br() </td> <td style="text-align:left;"> quebra de linha </td> </tr> <tr> <td style="text-align:left;"> code() </td> <td style="text-align:left;"> texto no estilo de código </td> </tr> <tr> <td style="text-align:left;"> h1(), ..., h6() </td> <td style="text-align:left;"> títulos </td> </tr> <tr> <td style="text-align:left;"> img() </td> <td style="text-align:left;"> imagem </td> </tr> <tr> <td style="text-align:left;"> p() </td> <td style="text-align:left;"> parágrafi </td> </tr> <tr> <td style="text-align:left;"> em() </td> <td style="text-align:left;"> texto itálico </td> </tr> <tr> <td style="text-align:left;"> strong() </td> <td style="text-align:left;"> texto em negrito </td> </tr> </tbody> </table> --- ## Grid System <img src="img/gridsystem.jpg"> - Cada linha é uma **`fluidRow()`**. - **`columns`** são divididas em 12 unidades. O **`width`** determina quantas partes de largura a coluna tem. .footnote[ source: [dzone.com/articles/working-with-bootstrap-4-grid-system-for-creating](https://dzone.com/articles/working-with-bootstrap-4-grid-system-for-creating) ] -- Grid System vem do [Bootstrap Framework](https://getbootstrap.com.br/docs/4.1/getting-started/introduction/) do Twitter. --- ## Grid System Duas principais funções ```r fluidRow() ``` ``` ## <div class="row"></div> ``` ```r column(2) ``` ``` ## <div class="col-sm-2"></div> ``` --- ## tabPanels and tabsetPanels ```r # ui tabsetPanel( tabPanel("Plot", plotOutput("plot")), tabPanel("Summary", verbatimTextOutput("summary")), tabPanel("Table", tableOutput("table")) ) ``` <img src="img/tabsetpanel.png"> --- ## pageWithSidebar Layout ```r pageWithSidebar( headerPanel = headerPanel("Hello Shiny!"), sidebarPanel( sliderInput("n", "Sample size:", min= 0, max=150, value=50) ), mainPanel( plotOutput("iris_plot") ) ) ``` <img src = "img/sidebarpage.png"> --- ## navbarPage Layout ```r navbarPage(title = "Minha página Navbar", tabPanel("a"), tabPanel("b"), tabPanel("c"), tabPanel("d") ) ``` output: <img src = "img/navbarpage.png"> --- ## shinydashboard Layout <img src="img/dashexample.png"> .footnote[ source: [db.rstudio.com/dashboards/](https://db.rstudio.com/best-practices/dashboards/) ] --- ## shinydashboard Layout ### O template .pull-left[ ```r ui <- dashboardPage( dashboardHeader(), dashboardSidebar(), dashboardBody() ) #server... ``` ] .pull-right[ <img src="img/shinydashboard.png"> ] --- ## shinydashboard Layout .pull-left[ ### box ```r box( title = "Histograma", ... ), box( title = "Inputs", ... ) ``` <img src="img/box.png"> ] .pull-right[ ### tabBox ```r tabBox( title = "Densidades", tabPanel("Sepal.Length",..), tabPanel("Sepal.Width",...), tabPanel("Petal.Length",..), tabPanel("Petal.Width",...) ) ``` <img src="img/tabbox.png"> ] --- ## shinydashboard Layout .pull-left[ ### valueBox <img src="img/valuebox.png"> **`renderValueBox({}) + valueBoxOutput()`** ] .pull-right[ ### infoBox <img src="img/infobox.png"> **`renderInfoBox({}) + infoBoxOutput()`** ] --- ## shinydashboard Layout ### dashboardHeader ```r dashboardPage( * dashboardHeader(title = "Iris Predictor"), dashboardSidebar(...), dashboardBody(...) ) #server... ``` <img src="img/dashboardHeader.png"> --- ## shinydashboard Layout #### dashboardSidebar + sidebarMenu + menuItem ```r dashboardSidebar( sidebarMenu( menuItem("Calculator", tabName = "calc"), menuItem("Descriptive", tabName = "desc") ) ) ``` #### dashboardBody + tabItems + tabItem ```r dashboardBody( tabItems( tabItem(tabName = "calc",...), tabItem(tabName = "desc",...) ) ) ``` --- ## Exercício 1 Replique o layout da aba "Calculator" [desse dashboard (click aqui!)](https://rseis.shinyapps.io/my-first-dashboard-with-shiny-csds2019/). <img src="img/dashtutorial.png"> --- ## Exercise 2 (hard!) Replique o layout da aba "Descriptive" [desse dashboard (click aqui!)](https://rseis.shinyapps.io/my-first-dashboard-with-shiny-csds2019/). <img src="img/dashtutorial2.png"> --- ## Deploy - [shinyapps.io](https://www.shinyapps.io/) 👋 🍭 👶 - [Shiny Server](https://rstudio.com/products/shiny/shiny-server/) 👩🔧 - [Serviços de nuvem (Google Cloud Plataform)](https://www.curso-r.com/blog/2019-09-06-app-deploy/) 💸 👩💻 - [RStudio Connect](https://rstudio.com/products/connect/) 💸 💸 💸 💸 💸 --- ## Referência Esse curso foi baseado no [Garrett Grolemund's Shiny Tutorial](https://shiny.rstudio.com/tutorial/).