¡Me alegra muchísimo que la app funcionara! Ahora, con gusto te preparo una guía didáctica completa para tus estudiantes. Aquí va paso a paso, pensando en que solo han trabajado con RMarkdown a nivel básico:
Shiny es un paquete de R que permite crear aplicaciones web interactivas sin necesidad de saber HTML, CSS ni JavaScript. Es como transformar tu análisis de R en una página web con botones, gráficos interactivos, tablas y formularios.
| Característica | RMarkdown | Shiny |
|---|---|---|
| Interactividad | Estático (PDF/HTML fijo) | Interactivo (botones, sliders, selectores) |
| Usuario | Solo lee el documento | Puede interactuar, cambiar datos, explorar |
| Ejecución | Se renderiza una vez | Se ejecuta en tiempo real |
| Ejemplo | Un informe PDF con gráficos | Un dashboard donde el usuario elige qué variable graficar |
RMarkdown: "Aquí está mi gráfico de dispersión..."
Shiny: "Elige la variable X: [dropdown] Elige la variable Y: [dropdown] [Generar Gráfico]"
shinyEn la consola de R (o en un chunk de RMarkdown), ejecuta:
install.packages("shiny")
library(shiny)
# Esto abre una app de ejemplo
shiny::runExample("01_hello")
Si ves una ventana con un slider y un histograma, ¡todo está listo!
install.packages("shinyjs") # Efectos visuales y utilidades
install.packages("bslib") # Temas bonitos (como Bootstrap)
install.packages("DT") # Tablas interactivas
install.packages("plotly") # Gráficos interactivos
install.packages("shinydashboard") # Dashboards profesionales
Una Shiny App tiene dos partes obligatorias, como el “cerebro” y el “cuerpo”:
Es el diseño visual: botones, títulos, gráficos, tablas.
Es el cerebro: qué hace cada botón, qué gráficos se generan, qué cálculos se hacen.
Crea un archivo llamado app.R y pega
esto:
library(shiny)
# ---- PARTE 1: UI (Lo que se ve) ----
ui <- fluidPage(
# Título
titlePanel("Mi Primera Shiny App"),
# Contenido
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "num", # ID interno
label = "Número de datos:", # Texto visible
min = 10, max = 500, value = 100)
),
mainPanel(
plotOutput(outputId = "histograma") # Dónde mostrar el gráfico
)
)
)
# ---- PARTE 2: SERVER (La lógica) ----
server <- function(input, output) {
output$histograma <- renderPlot({
datos <- rnorm(input$num) # Generar números aleatorios
hist(datos, col = "steelblue", main = "Histograma")
})
}
# ---- PARTE 3: Ejecutar ----
shinyApp(ui = ui, server = server)
app.R
(¡exactamente ese nombre!)Son los widgets que el usuario puede manipular:
sliderInput("id_slider", "Elige un número:", min = 1, max = 100, value = 50)
numericInput("id_numero", "Escribe un valor:", value = 10)
textInput("id_texto", "Escribe tu nombre:", value = "")
selectInput("id_selector", "Elige una opción:", choices = c("A", "B", "C"))
actionButton("id_boton", "Haz clic aquí")
dateInput("id_fecha", "Selecciona fecha:")
fileInput("id_archivo", "Sube un archivo:")
Regla mnemotécnica: Todo input tiene: - Un
inputId (nombre único para usar en el
server) - Un label (texto que ve el
usuario)
Son los resultados que se generan dinámicamente:
plotOutput("id_grafico") # Para mostrar gráficos
tableOutput("id_tabla") # Para mostrar tablas simples
dataTableOutput("id_tabla_dt") # Para tablas interactivas (paquete DT)
textOutput("id_texto") # Para mostrar texto
verbatimTextOutput("id_codigo") # Para mostrar código/resultados
uiOutput("id_ui_dinamica") # Para contenido HTML dinámico
En el server, cada output se crea con una función
render*():
server <- function(input, output) {
output$mi_grafico <- renderPlot({
# Código para crear el gráfico
plot(1:10, col = "blue")
})
output$mi_tabla <- renderTable({
# Código para crear la tabla
head(mtcars)
})
output$mi_texto <- renderText({
# Código para generar texto
paste("Hola, has elegido:", input$id_slider)
})
}
La conexión entre UI y Server se hace por nombres:
UI: plotOutput("histograma")
Server: output$histograma <- renderPlot({...})
UI: sliderInput("num", ...)
Server: input$num ← accede al valor del slider
library(shiny)
ui <- fluidPage(
titlePanel("Calculadora de Media"),
numericInput("n1", "Número 1:", value = 10),
numericInput("n2", "Número 2:", value = 20),
numericInput("n3", "Número 3:", value = 30),
h3("Resultado:"),
textOutput("resultado")
)
server <- function(input, output) {
output$resultado <- renderText({
media <- mean(c(input$n1, input$n2, input$n3))
paste("La media es:", round(media, 2))
})
}
shinyApp(ui, server)
library(shiny)
library(ggplot2)
ui <- fluidPage(
titlePanel("Explorador de Datos Iris"),
sidebarLayout(
sidebarPanel(
selectInput("xvar", "Variable X:",
choices = names(iris)[1:4], selected = "Sepal.Length"),
selectInput("yvar", "Variable Y:",
choices = names(iris)[1:4], selected = "Sepal.Width"),
selectInput("color", "Colorear por:",
choices = names(iris), selected = "Species")
),
mainPanel(
plotOutput("scatter")
)
)
)
server <- function(input, output) {
output$scatter <- renderPlot({
ggplot(iris, aes_string(x = input$xvar, y = input$yvar, color = input$color)) +
geom_point(size = 3) +
theme_minimal()
})
}
shinyApp(ui, server)
library(shiny)
library(DT)
ui <- fluidPage(
titlePanel("Lector de CSV"),
fileInput("archivo", "Sube un archivo CSV:", accept = ".csv"),
DTOutput("tabla")
)
server <- function(input, output) {
output$tabla <- renderDT({
req(input$archivo) # No ejecutar hasta que haya archivo
datos <- read.csv(input$archivo$datapath)
datatable(datos, options = list(pageLength = 10))
})
}
shinyApp(ui, server)
El paquete bslib permite usar temas modernos sin saber
CSS:
library(shiny)
library(bslib)
ui <- page_fluid(
theme = bs_theme(bootswatch = "flatly"), # Tema bonito
card(
card_header("Mi App Profesional"),
"Contenido aquí..."
)
)
server <- function(input, output) {}
shinyApp(ui, server)
Temas disponibles: cerulean,
cosmo, cyborg, darkly,
flatly, journal, lumen,
paper, readable, sandstone,
simplex, slate, spacelab,
superhero, united, yeti
rsconnect::setAccountInfo(name='tunombre',
token='ABC123XYZ',
secret='secreto-largo-aqui')
install.packages("rsconnect")
Método 1 (desde código):
library(rsconnect)
deployApp(appName = "mi-primera-app")
Método 2 (botón de RStudio): 1. Abre tu archivo
app.R 2. Haz clic en el botón azul Publish
(arriba a la derecha) 3. Selecciona ShinyApps.io 4.
Dale un nombre y ¡listo!
Aparecerá una URL como:
https://tunombre.shinyapps.io/mi-primera-app/
¡Puedes compartirla con cualquier persona!
mi-proyecto/
├── app.R # App principal
├── data/ # Datos
│ └── datos.csv
├── www/ # Imágenes, CSS personalizado
│ └── logo.png
└── README.md # Descripción del proyecto
req() para verificar que
los inputs existen antes de usarlosshinyjs::hide() y
shinyjs::show() para mostrar/ocultar
contenido| Error | Solución |
|---|---|
Error sourcing app.R |
Verifica que no hay for/if en la UI. Usa
lapply() |
object 'input$xxx' not found |
El inputId no existe en la UI |
cannot open the connection |
La ruta del archivo es incorrecta |
| La app se ve gris | Revisa la consola de RStudio, hay un error en el server |
| Error al publicar | Verifica que todos los paquetes estén instalados |
Con lo aprendido en esta guía, tus estudiantes ya pueden entender cómo funciona la app del Evaluador de Volantes de Pago. Los conceptos son los mismos:
| Recurso | Link |
|---|---|
| Galería oficial de ejemplos | shiny.rstudio.com/gallery |
| Cheatsheet de Shiny | rstudio.github.io/cheatsheets/shiny.pdf |
| Tutorial oficial | shiny.rstudio.com/tutorial |
| Foro de ayuda | community.rstudio.com/c/shiny |
| Documentación bslib | rstudio.github.io/bslib |
Espero que esta guía sea muy útil para tus estudiantes. Está diseñada para que un estudiante que solo sabe RMarkdown básico pueda, en aproximadamente 2 horas, crear y publicar su primera Shiny App. Si necesitas alguna aclaración o quieres que profundice en algún tema específico, con gusto lo hago.