Este es un tutorial para construir una aplicación web con funcionalidades basicas usando el software R.

Creación de una aplicación shiny

Una aplicación shiny tiene 2 funciones o archivos, uno llamado ui en donde se describe la interfaz gráfica de la aplicación, y otro llamado server en donde se escribe la lógica de la aplicación.

Para crear una nueva aplicación shiny:

Automaticamente se generarán 2 funciones ui y server, el software ya genera por default con una aplicación sencilla que genera un histograma de un conjunto predefinido de datos. Para correr la aplicación haga click en Run App en la parte superior de la ventana de edición de codigo.

Volviendo al archivo app.R se pueden identificar varios componentes de la aplicación. En primer lugar, el objeto ui es un fluid layout a partir del cual se organizan los objetos de la interfaz gráfica en filas y comlumnas.

¡Investiga!
¿Cuales argumentos recibe la función fluidPage()?

Algunas otras configuraciones y elementos de la interfaz gráfica se pueden encontrar aquí.

Entre los parámetros que recibe la función fluidPage() encontramos title el cual se asigna con la función titlePanel() y es el que da nombre a la aplicación. Por otro lado, la función sidebarLayout crea una estructura de interfaz gráfica con un panel lateral y un panel principal a los cuales se les pueden agregar diferentes elementos. Otro objeto que se observa la interfaz es un sliderInput() el cual es un control deslizante que permite seleccionar valores en un rango.

¡Investiga!
¿Cuales otros elementos o control widgets se pueden utilizar en shinny?

En el panel principal se puede observar que se toma el resultado de una función definida en el server y se renderiza en la aplicación con la función plotOutput().

Por otro lado, el servidor se define como una función con un parámetro de entrada input y un parámetro de salida output. Al objeto de salida se le asigna un objeto llamado distPlot el cual renderiza una gráfica a partir del parámetro input$bins

¡Ponte a prueba!
Cambia el nombre de la aplicación a Aplicación bancaria, cambia el número mínimo del control deslizante a 5 y el valor por defecto a 10 y cambia el color del histograma a verde.

Aplicación centro de salud

En esta parte vamos a construir una herramienta que permita estimar el número de exámenes de laboratorio y el porcentaje de médicos especialistas requeridos en un centro de salud en un mes. ### Creación de interfaz gráfica

Primero vamos a diseñar la interfaz, ubicaremos un sliderInput para cada parámetro que permita seleccionar el valor deseado, en la función ui reemplazamos el contenido de ui <-fluidPage( … ) por el que se muestra a continuación:

 # Application title
  titlePanel("Estimación de personal y exámenes requeridos por mes"),
  
  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      sliderInput("nConsultas",
                  "Número de consultas mensuales",
                  min = 0,
                  max = 80,
                  value = 30),
      sliderInput("pMayores",
                  "Porcentaje de personas mayores de 50 años",
                  min = 0,
                  max = 1,
                  value = 0.3)
    ),
    
    # Show a plot of the generated distribution
    mainPanel(
      plotlyOutput("numExamenes"),
      plotlyOutput("pie")
    )
  )

Este código crea 2 formularios en la barra lateral, y guarda espacio en el panel principal para 2 gráficos, uno para el número de examenes requeridos y otro para el porcentaje de especialistas requeridos.

La aplicación en este momento debería verse así:

Creación de la lógica de aplicación

Hasta el momento tenemos el esqueleto de una interfaz, sin embargo para que esta realice cualquier acción se requiere de funciones que son definidas en la función server.

Primero vamos a eliminar todo el contenido dentro de la función server de forma que lo único que quede es la definición de la función como se muestra a continuación:

server <- function(input, output) {
   
   
}

A continuación vamos a definir la lógica a partir de la cual se crean los gráficos.

  1. Número de exámenes de laboratorio requeridos

Para el calculo del número de exámenes de laboratorio requeridos, se conoce que en promedio los adultos mayores se deben tomar 1.2 exámenes de sangre, 0.8 exámenes de orina y 1.9 exámenes de tejidos al mes. Por otro lado, el resto de los pacientes se toman 0.5 exámenes de sangre, 0.3 exámenes de orina y 0.8 exámenes de tejidos al mes. Para conocer el número total de exámenes de cada tipo requeridos al mes, realizamos los siguientes cálculos:

 numExSangre= input$nConsultas*input$pMayores*1.2+input$nConsultas*(1-input$pMayores)*0.5
    numExOrina= input$nConsultas*input$pMayores*0.8+input$nConsultas*(1-input$pMayores)*0.3
    numExTejidos= input$nConsultas*input$pMayores*1.9+input$nConsultas*(1-input$pMayores)*0.8

Para crear una gráfica de barras que presente los cálculos anteriores agregamos el siguiente código a la función server.

  output$numExamenes <- renderPlotly({
    
    numExSangre= input$nConsultas*input$pMayores*1.2+input$nConsultas*(1-input$pMayores)*0.5
    numExOrina= input$nConsultas*input$pMayores*0.8+input$nConsultas*(1-input$pMayores)*0.3
    numExTejidos= input$nConsultas*input$pMayores*1.9+input$nConsultas*(1-input$pMayores)*0.8
    
    datos = data.frame(Examen = c("Sangre","Orina", "Tejidos corporales"),
                       numeroExamenes = c(numExSangre,numExOrina,numExTejidos))
    plot_ly(datos, x = ~Examen, y = ~numeroExamenes)
  })

Ahora corremos la aplicación nuevamente y podemos observar la nueva gráfica.

  1. Porcentaje de médicos requeridos

Queremos diferenciar 3 tipos de especialistas; internistas, neumólogos y cardiólogos. Sabemos que el 40% de los adultos mayores consultan a un médico internista, 20% a un neumólogo y 10% a un cardiólogo. Por otro lado, el 20% los pacientes consultan a un internista, 50% a un neumólogo y 20% a un cardiólogo.

De acuerdo con lo anterior, agregamos a la función server los cálculos correspondientes y creamos un pie utilizando la librería plotly.

output$pie <- renderPlotly({
    numInternista=input$nConsultas*input$pMayores*0.4+input$nConsultas*(1-input$pMayores)*0.2
    numNeumologo=input$nConsultas*input$pMayores*0.2+input$nConsultas*(1-input$pMayores)*0.5
    numCardiologo=input$nConsultas*input$pMayores*0.1+input$nConsultas*(1-input$pMayores)*0.2
    numOtros=input$nConsultas*input$pMayores*0.3+input$nConsultas*(1-input$pMayores)*0.1
    datos = data.frame(Medico = c("Internista","Neumólogo","Cardiólogo","Otro"),
                       Prob = c(numInternista,numNeumologo,numCardiologo,numOtros))
    plot_ly(datos, labels = ~Medico, values = ~Prob, type = "pie")
  })

Ahora que tenemos la lógica de servidor podemos correr la aplicación web, esto se hace haciendo click en el boton Run App en la parte superior de la ventana de desarrollo.

El resultado final debería ser:

  1. Modificar parámetros a partir de un archivo

Ahora, el centro médico quiere poder subir los registros de pacientes del último mes y calcular a partir de este registro el número estimado de exámenes. En el registro se encuentra la identificación del paciente, el tipo de paciente (mayor (M) u otro (O)) y el número de exámenes que requirió de cada tipo. Si queremos modificar algunos parámetros del modelo a partir de un archivo, en primer lugar tenemos que crear en la vista la entrada que nos va a permitir seleccionar el archivo, esta entrada se llama fileInput. Esta función recibe como parámetro el identificador de la entrada, la descripción y el tipo de archivos que deja seleccionar, entre otros.

fileInput('archivo1', 'Seleccione un archivo xlsx',accept=c(".xlsx"))

A continuación agregamos el fileInput a la interfaz gráfica y el objeto plotly donde se graficarán nuestros resultados.

 # Application title
  titlePanel("Estimación de personal y exámenes requeridos por mes"),
  
  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      sliderInput("nConsultas",
                  "Número de consultas mensuales",
                  min = 0,
                  max = 80,
                  value = 30),
      sliderInput("pMayores",
                  "Porcentaje de personas mayores de 50 años",
                  min = 0,
                  max = 1,
                  value = 0.3),
      fileInput('archivo1', 'Seleccione un archivo xlsx',accept=c(".xlsx"))

    ),
    
    mainPanel(
      #Agregamos un título a cada gráfica
      h4("Número de exámenes estimados"),
      plotlyOutput("numExamenes"),
      h4("Porcentaje de especialistas requeridos"),
      plotlyOutput("pie"),
      h4("Número de exámenes según registro"),
      #También agregamos el objeto donde se graficarán nuestros resultados
      "Debe cargar un archivo para ver los resultados",
      plotlyOutput("tabla")
    )
  )

Luego, para obtener los datos del archivo seleccionado podemos utilizar la librería readxl. Después de instalarla e importarla procedemos a obtener el nombre del archivo desde el servidor para cargarlo en la lógica de nuestra aplicación y así utilizarlo posteriormente.

library(readxl)

#Dentro de la función server escribimos la lógica para tomar los datos del archivo, procesarlos y enviarlos a la interfaz
output$graficoTabla({
#Primero obtenemos el archivo desde la interfaz
    archivo1 <- input$archivo1
    if(is.null(archivo1))
      return(NULL) 
    #Leemos el archivo como un excel
    tabla<-read_excel(archivo1$datapath , 1)
    #Procesamos el archivo
    
    #1. Calculamos el número de personas mayores en el registro
    
    #Con la función which buscamos en la fila de tipo de usuario aquellos que son mayores
    #which nos retorna un vector lógico, calculando su tamaño sabemos cuántos registros cumplen la condición dada
    nMayores<-length(which(tabla[,2]=="M"))
    nOtros<-length(which(tabla[,2]=="O"))
    probabilidadMayores<-nMayores/(nMayores+nOtros)
    probabilidadOtros<-nOtros/(nMayores+nOtros)
    
    
    #2. Calculamos el promedio de exámenes de cada tipo requeridos para cada tipo de paciente
    
    #Obtenemos los registros únicamente de adultos mayores
    registrosMayores<-data.frame(tabla[which(tabla[,2]=="M"),])
    #Calculamos el promedio de examenes para adultos mayores
    pSangreMayores<-mean(registrosMayores[,3])
    pOrinaMayores<-mean(registrosMayores[,4])
    pTejidosMayores<-mean(registrosMayores[,5])
    pMayores<-c(pSangreMayores,pOrinaMayores,pTejidosMayores)
    
    #Obtenemos los registros únicamente de otros pacientes
    registrosOtros<-data.frame(tabla[which(tabla[,2]=="O"),])
    
    #Calculamos el promedio de examenes para otros pacientes
    pSangreOtros<-mean(registrosOtros[,3])
    pOrinaOtros<-mean(registrosOtros[,4])
    pTejidosOtros<-mean(registrosOtros[,5])
    pOtros<-c(pSangreOtros,pOrinaOtros,pTejidosOtros)
    
    #Ahora calculamos el número de exámenes estimados requeridos a partir de los datos del archivo xlsx
    numExSangre= input$nConsultas*probabilidadMayores*pSangreMayores+input$nConsultas*probabilidadOtros*pSangreOtros
    numExOrina= input$nConsultas*probabilidadMayores*pOrinaMayores+input$nConsultas*probabilidadOtros*pOrinaOtros
    numExTejidos= input$nConsultas*probabilidadMayores*pTejidosMayores+input$nConsultas*probabilidadOtros*pTejidosOtros
    
    datos = data.frame(Examen = c("Sangre","Orina", "Tejidos corporales"),
                       numeroExamenes = c(numExSangre,numExOrina,numExTejidos))
    
    #Enviamos a la interfaz el resultado
    plot_ly(datos, x = ~Examen, y = ~numeroExamenes, type = "bar", color = I("light blue"))
    
    
})

El resultado tras cargar el archivo es: