Tendencias Temporales

Row

Evolución diaria de registros

Proporción de altas médicas

Análisis por Servicio

Row

Distribución por servicio médico

Mapa de calor de actividad

Tipos de Alta y Observaciones

Row

Distribución de vías de alta

Registros prioritarios (rojos)

Datos Completos

---
title: "Análisis de Ocupación Hospitalaria"
author: "Diego Meza"
date: "2025-08-12"
output: 
  flexdashboard::flex_dashboard:
    theme: flatly
    social: menu
    source_code: embed
    orientation: rows
    vertical_layout: fill
---

```{r setup, include=FALSE}
library(tidyverse)
library(lubridate)
library(plotly)
library(highcharter)
library(DT)
library(glue)
library(flexdashboard)
library(viridis)
library(shiny)

# Configuración global
options(scipen = 999)

# Carga y preparación de datos
camas <- readxl::read_excel("mapeo_camas_admision_base.xlsx", sheet = "base") %>%
  mutate(
    fecha = ymd(fecha),
    semana = floor_date(fecha, "week"),
    esalta = factor(esalta, levels = c("SÍ", "No"), 
                   labels = c("Alta médica", "Paciente activo")),
    viadealta = case_when(
      viadealta == "No encontrado en listado" ~ "Registro inconsistente",
      viadealta == "Sigue figurando en el sistema" ~ "Alta no procesada",
      TRUE ~ viadealta
    ),
    prioridad = ifelse(color_observacion == "rojo", "Alta prioridad", "Normal")
  )
```

Filtros {.sidebar}
=====================================
   
```{r}
# Filtros interactivos
selectInput("servicio", "Seleccionar Servicio:",
            choices = c("Todos", unique(camas$servicio)))

dateRangeInput("rango_fechas", "Rango de Fechas:",
               start = min(camas$fecha),
               end = max(camas$fecha))

checkboxGroupInput("tipo_alta", "Tipo de Alta:",
                   choices = c("Alta médica", "Paciente activo"),
                   selected = c("Alta médica", "Paciente activo"))
```

Tendencias Temporales
=====================================
   
Row 
-----------------------------------------------------------------------

### Evolución diaria de registros

```{r}
renderHighchart({
  req(input$rango_fechas)
  
  df <- camas %>%
    filter(fecha >= input$rango_fechas[1],
           fecha <= input$rango_fechas[2],
           esalta %in% input$tipo_alta)
  
  if(input$servicio != "Todos") {
    df <- df %>% filter(servicio == input$servicio)
  }
  
  df %>%
    count(fecha, esalta) %>%
    hchart("column", hcaes(x = fecha, y = n, group = esalta)) %>%
    hc_title(text = "Registros Diarios por Estado") %>%
    hc_colors(c("#FF6B6B", "#4ECDC4")) %>%
    hc_xAxis(title = list(text = "Fecha")) %>%
    hc_yAxis(title = list(text = "Número de Registros")) %>%
    hc_exporting(enabled = TRUE)
})
```

### Proporción de altas médicas

```{r}
renderHighchart({
  req(input$rango_fechas)
  
  df <- camas %>%
    filter(fecha >= input$rango_fechas[1],
           fecha <= input$rango_fechas[2])
  
  if(input$servicio != "Todos") {
    df <- df %>% filter(servicio == input$servicio)
  }
  
  df %>%
    count(fecha, esalta) %>%
    group_by(fecha) %>%
    mutate(prop = n/sum(n)*100) %>%
    ungroup() %>%
    filter(esalta == "Alta médica") %>%
    hchart("line", hcaes(x = fecha, y = prop)) %>%
    hc_title(text = "Porcentaje Diario de Altas Médicas") %>%
    hc_colors("#1A535C") %>%
    hc_yAxis(title = list(text = "% de Altas"), max = 100) %>%
    hc_tooltip(valueSuffix = "%")
})
```

Análisis por Servicio
=====================================
   
Row 
-----------------------------------------------------------------------

### Distribución por servicio médico

```{r}
renderPlotly({
  req(input$rango_fechas)
  
  df <- camas %>%
    filter(fecha >= input$rango_fechas[1],
           fecha <= input$rango_fechas[2],
           esalta %in% input$tipo_alta)
  
  if(input$servicio != "Todos") {
    df <- df %>% filter(servicio == input$servicio)
  }
  
  df_sum <- df %>%
    count(servicio, esalta) %>%
    group_by(servicio) %>%
    mutate(prop = n/sum(n)*100) %>%
    ungroup() %>%
    arrange(desc(n))
  
  p <- ggplot(df_sum, aes(x = reorder(servicio, n), 
                y = n, fill = esalta,
                text = paste0(servicio, "\n", n, " registros (", round(prop), "%)"))) +
    geom_bar(stat = "identity") +
    coord_flip() +
    labs(title = "Distribución por Servicio Médico",
         x = "Servicio",
         y = "Número de Registros",
         fill = "Estado") +
    scale_fill_manual(values = c("#FF6B6B", "#4ECDC4")) +
    theme_minimal()
  
  ggplotly(p, tooltip = "text")
})
```

### Mapa de calor de actividad

```{r}
renderHighchart({
  req(input$rango_fechas)
  
  df <- camas %>%
    filter(fecha >= input$rango_fechas[1],
           fecha <= input$rango_fechas[2])
  
  if(input$servicio != "Todos") {
    df <- df %>% filter(servicio == input$servicio)
  }
  
  df %>%
    count(fecha, servicio) %>%
    hchart("heatmap", hcaes(x = fecha, y = servicio, value = n)) %>%
    hc_title(text = "Actividad Hospitalaria por Día") %>%
    hc_colorAxis(min = 0, stops = color_stops(colors = viridis(10))) %>%
    hc_xAxis(title = list(text = "Fecha")) %>%
    hc_yAxis(title = list(text = "Servicio"))
})
```

Tipos de Alta y Observaciones
=====================================
   
Row 
-----------------------------------------------------------------------

### Distribución de vías de alta

```{r}
renderPlotly({
  req(input$rango_fechas)
  
  df <- camas %>%
    filter(fecha >= input$rango_fechas[1],
           fecha <= input$rango_fechas[2],
           esalta == "Alta médica")
  
  if(input$servicio != "Todos") {
    df <- df %>% filter(servicio == input$servicio)
  }
  
  df_sum <- df %>%
    count(viadealta) %>%
    mutate(prop = n/sum(n)*100)
  
  plot_ly(df_sum, labels = ~viadealta, values = ~n, type = "pie",
          textinfo = "label+percent",
          insidetextorientation = "radial",
          marker = list(colors = RColorBrewer::brewer.pal(nrow(df_sum), "Set3"))) %>%
    layout(title = "Distribución de Tipos de Alta Médica",
           showlegend = FALSE)
})
```

### Registros prioritarios (rojos)

```{r}
renderDataTable({
  req(input$rango_fechas)
  
  df <- camas %>%
    filter(color_observacion == "rojo",
           fecha >= input$rango_fechas[1],
           fecha <= input$rango_fechas[2])
  
  if(input$servicio != "Todos") {
    df <- df %>% filter(servicio == input$servicio)
  }
  
  datatable(
    df %>% select(fecha, nombre_apellido, servicio, observacion, viadealta),
    rownames = FALSE,
    colnames = c("Fecha", "Paciente", "Servicio", "Observación", "Vía de Alta"),
    options = list(
      pageLength = 5,
      dom = "tip",
      language = list(
        url = '//cdn.datatables.net/plug-ins/1.10.11/i18n/Spanish.json'
      )
    )
  ) %>%
    formatStyle(columns = 1:5, backgroundColor = "#FFF3CD")
})
```

Datos Completos
=====================================
   
```{r}
renderDataTable({
  req(input$rango_fechas)
  
  df <- camas %>%
    filter(fecha >= input$rango_fechas[1],
           fecha <= input$rango_fechas[2])
  
  if(input$servicio != "Todos") {
    df <- df %>% filter(servicio == input$servicio)
  }
  
  datatable(
    df,
    extensions = "Buttons",
    options = list(
      dom = "Bfrtip",
      buttons = c("copy", "csv", "excel"),
      pageLength = 10,
      autoWidth = TRUE,
      language = list(
        url = '//cdn.datatables.net/plug-ins/1.10.11/i18n/Spanish.json'
      )
    ),
    colnames = c("Fecha", "Paciente", "Sala", "Registro", "Servicio", 
                 "Observación", "Es Alta", "Vía Alta", "Color Obs", 
                 "Clasificación Obs", "Fuente", "Página")
  )
})
```