Este documento é referente ao estudo do pacote Shiny motivado pela monitoria de Inferência Estatística 1 do semestre de 2018.1
Professora: Renata Bueno
Aluno: Rafael Cabral Fernandez
O que é ?
Um aplicativo Shiny é uma página web (UI ou User Interface) conectada a um computador contendo uma sessão ativa do R (Server), permitindo assim, a criação de programas interativos.
Em outras palavras, permite com que o usuário final do conteúdo consiga alterar os parâmetros de um programa sem que o mesmo tenha acesso aos códigos.
Estruturação Básica de um aplicativo Shiny:
De forma bastante resumida:
UI <- Onde é criado a interface para o usuário final, aqui onde serão definidos os parâmetros que estarão dispostos nas interações tão bem com a layout da página.
Server <- Aqui será inscrita a função que deseja-se aplicar sobre os parâmetros. A função, diferente dos parâmetros, é fixa e inalterável, na qual o usuário final não tem acesso.
shinyApp <- Combina o UI e o Server e os transforma em um aplicativo funcional.
Exemplo: Dentro da estruturação do código de um aplicativo Shiny, suponha que desejamos criar um gráfico interativo de um Histograma. A grosso modo, dentro do UI definiremos um raio de tamanho de amostra e dentro do Server escreveremos a função do Histograma.
Observação: A estrutura é diferente se utilizarmos um script comum ou o R Markdown. Na primeira opção, devemos escrever dois scripts, um para a UI e um para o Server. No R Markdown, conseguimos compilar todas as funções no mesmo bloco.
Na prática, teremos algo no seguinte formato:
library(shiny)
ui <- fluidPage( )
server <- function( input , output ){}
shinyApp ( ui = ui , server = server )Código dentro do R:
ui <- fluidPage(
titlePanel("title panel"),
sidebarLayout(
sidebarPanel("sidebar panel"),
mainPanel("main panel")
)
)Resultado:
A estruturação básica do user interface pode conter:
titlePanel: Um título para o aplicativo Shiny
sidebarPanel: Siderbar é onde definiremos os valores interativos do nosso programa, faremos um Input (uma entrada) como uma determinada função pré-estabelecida. Veremos mais a frente que existem varios tipos de Input. É aqui que o usuário final irá interagir com o aplicativo.
mainPanel: Aqui é possível definir qual tipo de resposta o usuário final. Vimos que no sidebarPanel existe o Input, ou a entrada, aqui teremos o Output, ou a saída.
Possíveis inputs que podemos colocar no sidebarPanel como variáveis para o usuário integarir:
Fonte: LondoR Workshop
Em outras palavras, quando olhamos a tabela, é possível identificar que conseguimos criar uma variável de entrada do tipo texto (textInput), ou seja, estamos forçando o usuário a entrar com alguma letra, palavra ou frase para que seja retornado algo de interesse do mesmo. Podemos também criar variáveis numéricas discretas, contínuas (sliders), listas, etc. Existe uma gama de possíveis inputs que o Shiny permite.
Perceba que como mencionado anteriormente, o argumento Input é inserido dentro do sidebarPanel, pois é lá que o usuário entrará com o texto (caso seja definido um textIntput). Analogamente, existirá um textOutput, ou uma saída de texto, caso deseja-se uma resposta interativa textual. Este argumento, por sua vez, virá dentro do mainPanel.
ui <- fluidPage(
titlePanel("Titulo"),
sidebarLayout(
sidebarPanel("Painel Lateral"),
mainPanel("Painel Principal")
)
)
server <- (function(input, output){})
shinyApp(ui, server)…
Interativo ?
Ainda não.
Apesar de ter sido formulado e postado como um aplicativo shiny, este exemplo não é interativo. Repare que usamos a mesma formulação proposta na aba “User Interface”, apenas alterando os nomes.
A resposta é muito simples e se encontra no código do próprio programa: Apesar de termos definido um UI, NÃO DEFINIMOS UM SERVER.
Este exemplo foi criado para nos lembrar de um dos conceitos mais básicos de um aplicativo shiny: O que torna um programa interativo é a relação entre o UI e o Servidor, os dois precisam coexistir por meio do ShinyApp. Uma interface sem um servidor por trás é tão somente uma casca vazia.
server <- function(input, output) {
output$value <- renderFunction({input$obs})O servidor é uma função com dois parâmetros, o Input e o Output.
Mas o que tem a ver com Input e o Output da Interface ?
TUDO
O servidor receberá alguma entrada Input criado pela Interface, processará através de uma função e devolverá por meio da saída Output.
Intuição:
Computacionalmente falando, o servidor é uma função que processa a interface, sendo dependente de dois parâmetros, o Input e o Output, estes declarados anteriormente.
Quando olhamos a estrutura da programação do servidor, conseguimos notar que, grosseiramente, o output <- render(input). O que isto quer dizer ?
O output recebe uma transformação do input através da função Render, nativa do Shiny e muito importante para nós. Ela que receberá os valores que o usuário final estiver interessado em testar, transformará e devolverá os resultados adequados. Assim como o Input para o UI, o Render tem uma variedade de funções atreladas ao mesmo, aqui vai uma tabela com alguns exemplos:
Fonte: Shiny cheat sheet
ui <- fluidPage(
numericInput("obs", "Observacoes:", 10, min = 1, max = 100),
verbatimTextOutput("value")
)
server <- function(input, output) {
output$value <- renderText({ input$obs })
}
shinyApp(ui, server)Agora sim, um programa interativo!
Vamos tentar construir e ler aos poucos o que o programa faz
ui <- fluidPage()FluidPage é uma função que define o Layout do aplicativo, que vai se aquedar ao tamanho da página.
ui <- fluidPage(numericInput("obs", "Observacoes:", 10, min = 1, max = 100))numericInput cria uma entrada com valores numéricos. Vamos agora observas os parâmetros declarados
“obs” = nome da variável numerica dentro do programa
“Observações:” Como a variável irá aparecer no aplicativo
10 = valor default
min e max autoexplicativos
ui <- fluidPage(
numericInput("obs", "Observacoes:", 10, min = 1, max = 100),
verbatimTextOutput("value")
)verbatimTextOutput renderiza a variável como um texto verbatim, que em outras palavras, significa “sem alteração”.
ui <- fluidPage(
numericInput("obs", "Observacoes:", 10, min = 1, max = 100),
verbatimTextOutput("value")
)
server <- function(input, output) {
output$value <- renderText({ input$obs })
}
shinyApp(ui, server)Repare que “obs” é o nome do Input dentro do UI. Já no servidor, para fazermos a relação, basta escrevermos input$obs, funciona analogamente para o output e value. A função renderText renderiza o valor posto em Obs e joga para Value em verbatim, ou seja, sem alteração. Por fim, a função ShinyApp mescla o UI com o Servidor, tornando o aplicativo funcional.
O aplicativo aqui construído simplesmente permite com que o usuário selecione um número discreto entre 1 e 100 e o imprime embaixo. O objetivo é mostrar que até mesmo algo simples e sem muita verticalidade ou uso prático pode ter uma construção não trivial dentro do Shiny.
ui <- fluidPage(numericInput(inputId = "n","Tamanho da amostra", value = 25),
plotOutput(outputId = "hist"))
server <- function(input, output) {
output$hist <- renderPlot({hist(rnorm(input$n),main="Histograma de variaveis aleatorias", ylab="Frequencia", xlab="Valores gerados por uma VA Normal")
})
}
shinyApp(ui = ui, server = server)Agora iremos para a primeira aplicação estatística do Shiny.
Como o programa foi construído:
ui <- fluidPage(numericInput(inputId = "n","Tamanho da amostra", value = 25))Mais uma vez, utilizaremos o fluidPage para o Layout. Entraremos com um numericInput dado os seguintes parâmetros
InputId = “n” é o nome da variável, diferente do exemplo 1, deixamos explícito o nome do parâmetro (InputdId)
“Tamanhao da Amostra” segue como o nome que será mostrado no layout
25 será o valor default de escolha
ui <- fluidPage(numericInput(inputId = "n","Tamanho da amostra", value = 25),
plotOutput(outputId = "hist"))O Output desta vez será do tipo Plot, ou seja, um gráfico. O chamaremos de Hist. Note que o OutputId é o parâmetro de nomeação.
ui <- fluidPage(numericInput(inputId = "n","Tamanho da amostra", value = 25),
plotOutput(outputId = "hist"))
server <- function(input, output) {
output$hist <- renderPlot({hist(rnorm(input$n),main="Histograma de variaveis aleatorias", ylab="Frequencia", xlab="Valores gerados por uma VA Normal")
})
}
shinyApp(ui = ui, server = server)Agora iremos para a montagem do servidor. Desta vez, diferente do exemplo anterior, usaremos a função renderPlot, que como o nome sugere, renderiza gráficos. Faremos o Output receber um Histograma do Rnorm do Input.
Em outras palavras, estamos gerando um histograma baseado numa amostrada gerada por uma distribuição normal. Note que se selecionar uma amostra de mesmo tamanho duas vezes, não terá o mesmo histograma, isto é porque o efeito aleatório ainda se faz presente, poderiámos “corrigir” com um set.seed se assim quisermos.