El paquete Shiny es una contribucion gratuita a R, provee una forma fácil y rapida de desarrollo de productos de datos a travez de navegadores web modernos. Shiny viene con una variedad de widgets para la construcción rapida de interfaces de usuario web, nosotros escribimos el codigo en R y shiny hará el trabajo pesado de generar el HTML, css, javascript, jquery, etc.
Bibliografía:
Web application development with R using Shiny, Chris Beeley, 2013, Packt Publishing Ltd.
Para crear un nuevo proyecto shiny desde R Studio existen varias formas, se puede utilizar un R Script en blanco o utilizar el asistente.
Para crear una App Shiny basta con tener 2 funciones: ui y server, en la parte UI vamos a dibujar la interfaz de usuario colocando todos los componentes que queremos mostrar, y en la parte del server vamos a colocar la lógica de programación.
En R Studio: creamos un script en blanco, lo guardamos como “app.R” y pegamos el siguiente código.
library(shiny)
# Ejemplo clásico en shiny
# en UI declaramos la interface de usuario
ui <- fluidPage(
# ingresamos un titulo
titlePanel("Old Faithful Geyser Data"),
# sidebar es una seccion de la página web que estara a la izquierda de la pantalla
# aquí ponemos un control para el numero de agrupaciones de un histograma
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# mainpanel es la seccion principal que estará al centro de la pantalla
# aqui pondremos los graficos o productos de datos principales de nuestra visualización
mainPanel(
plotOutput("distPlot")
)
)
)
# La parte del server contiene la lógica de la programación,
# aquí pondremos que se va a graficar y si es necesario una transformación de datos
# tiene que estar aquí
# recibe dos parámetros
# input: todos los componenetes de entrada, ejemplo: una lista de selección
# output: todos los componentes de salida donde vamos a escribir o graficar
server <- function(input, output) {
# la variable output contendra todas las variables que definimos en el UI
# en este caso vamos a dibujar un histograma
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
}
# Escencial para cuando utilizamos un solo archivo.
shinyApp(ui = ui, server = server)
Para una app pequeña el modelo anterior funciona muy bien, pero ahora que pasa si la complejidad de la aplicacion crece y nos deja como resultado un archivo gigante con muchas líneas de código, por esta razón vamos a dividir el archivo anterior en 2: ui.R y server.R y vamos a copiar cada pedazo de código de la siguiente forma:
library(shiny)
# Ejemplo clásico en shiny
# en UI declaramos la interface de usuario
ui <- fluidPage(
# ingresamos un titulo
titlePanel("Old Faithful Geyser Data"),
# sidebar es una seccion de la página web que estara a la izquierda de la pantalla
# aquí ponemos un control para el numero de agrupaciones de un histograma
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# mainpanel es la seccion principal que estará al centro de la pantalla
# aqui pondremos los graficos o productos de datos principales de nuestra visualización
mainPanel(
plotOutput("distPlot")
)
)
)
library(shiny)
# La parte del server contiene la lógica de la programación,
# aquí pondremos que se va a graficar y si es necesario una transformación de datos
# tiene que estar aquí
# recibe dos parámetros
# input: todos los componenetes de entrada, ejemplo: una lista de selección
# output: todos los componentes de salida donde vamos a escribir o graficar
server <- function(input, output) {
# la variable output contendra todas las variables que definimos en el UI
# en este caso vamos a dibujar un histograma
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
}
Nos aseguramos que los dos archivos esten en la misma carpeta, y para ejecutar vamos a la consola y ponemos el siguiente código
runApp("c:/directorio/aplicacion")
Otra opción para ejecutar es ir a ui.R y dar click en el botón -> Run
Para una mejor organización recomiendo usar el asistente para crear proyectos, y dentro del proyecto crear una carpeta por aplicación, de esta forma tenemos todos las aplicaciones identificadas y nos va a ser más fácil linkearlos.
Shiny por defecto trae varios esquemas de presentacion (layouts), estos esquemas nos permiten tener dividida la pantalla en secciones y lo único que debemos hacer es ir rellenandolas con nuestros objetos
del HTML resultante, los paneles disponibles son:
absolutePanel()
conditionalPanel()
fixedPanel()
headerPanel()
inputPanel()
mainPanel()
navlistPanel()
sidebarPanel()
tabPanel()
tabsetPanel()
titlePanel()
wellPanel()
Los layouts se utilizan para organizar los paneles y elementos dentro de un layout existente.
Ejemplo:
library(shiny)
fluidPage(
titlePanel("Hello Shiny!"),
sidebarLayout(
sidebarPanel(HTML('<p>
<label>A numeric input:</label><br />
<input type="number" name="n" value="7" min="1" max="30" />
</p>')),
mainPanel(
p(strong("bold font "), em("italic font")),
p(code("code block")),
a(href="http://www.google.com", "link to Google"))
)
)
Los widgets son controles con los que el usuario va a interactuar, es decir que mediante estos controles el usuario va a comunicarse con nuestra aplicacion, filtrar, seleccionar, ingresar un dato por parámetro.
| function | widget |
|---|---|
| actionButton | Botón para acciones |
| checkboxGroupInput | Un grupo de checkboxes |
| checkboxInput | Un simple checkbox |
| dateInput | Seleccion de una fecha |
| dateRangeInput | Seleccion de un par de fechas |
| fileInput | Subir un archivo |
| helpText | Texto de ayuda para otro control |
| numericInput | Campo para insertar un dato numérico |
| radioButtons | Un grupo de radio buttons |
| selectInput | Clasica caja con opciones para seleccionar |
| sliderInput | Control para seleccionar un dato numérico |
| submitButton | Un boton de submit |
| textInput | Campo para ingresar un dato de texto |
library(shiny)
fluidPage(
#título
titlePanel("Mi primera Shiny App"),
sidebarLayout(
sidebarPanel(
numericInput("numInput", "Ingresa un número:", value = 7, min = 1, max = 30)
),
mainPanel(
p(strong("bold font "), em("italic font")),
p(code("code block")),
a(href="http://rusersgroup.com/", "R User Group"))
)
)
Ya que temos listo nuestro UI, vamos a enlazarlo con el server.
Para graficar cualquier elemento debemos entender que hace la parte del output, el output trabaja tanto con el UI como con el server mediante las funciones render() y output()
Como vemos en la imagen anterior cada elemento que queremos graficar tiene una función que colocaremos en el UI y otra en el Server.
| Output | function render | function creates |
|---|---|---|
| htmlOutput/uiOutput | renderUI | Salida para HTML |
| imageOutput | renderImage | Imagenes |
| plotOutput | renderPlot | gráficos |
| tableOutput | renderTable | Para imprimir una tabla (data frame, matrix, etc) |
| textOutput | renderText | salidas de texto |
| verbatimTextOutput | renderPrint | imprimir texto (ej: summary(cars)) |
library(shiny)
fluidPage(
titlePanel("Hello Shiny!"),
sidebarLayout(
sidebarPanel(
numericInput("numInput", "A numeric input:", value = 7, min = 1, max = 30)
),
mainPanel(
textOutput("txtOutput")
)
)
)
library(shiny)
function(input, output) {
output$txtOutput = renderText({
paste0("The area of the circle is: ", pi*input$numInput^2)
})
}