#install.packages("dplyr")
#install.packages("ggplot2")
library(dplyr)  ## Manipulación de datos
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2) ## Creación de visualizaciones
##Carga de las bases de datos 

load("base_final_graficos.Rdata")
# Cargar la base de datos
load("base_final_graficos.Rdata")

# Ver las primeras filas de la base principal
head(base_final_long)
## # A tibble: 6 × 8
##   codigo_municipio nombre_municipio Sexo  Fuente  anio casos Codigo Departamento
##   <chr>            <chr>            <chr> <chr>  <int> <dbl> <chr>  <chr>       
## 1 19001            Popayán          F     RIPS    2009   248 19     Cauca       
## 2 19001            Popayán          F     RIPS    2010   493 19     Cauca       
## 3 19001            Popayán          F     RIPS    2011  1174 19     Cauca       
## 4 19001            Popayán          F     RIPS    2012  2230 19     Cauca       
## 5 19001            Popayán          F     RIPS    2013  3394 19     Cauca       
## 6 19001            Popayán          F     RIPS    2014  4667 19     Cauca
# Tomo el objeto cargado (base_final_long) y lo renombro
stopifnot(exists("base_final_long"))
base_final_grafico <- tibble::as_tibble(base_final_long)

# Chequeo rápido
dim(base_final_grafico)
## [1] 3894    8
# Estructura y dimensiones
str(base_final_grafico)         # estructura base R
## tibble [3,894 × 8] (S3: tbl_df/tbl/data.frame)
##  $ codigo_municipio: chr [1:3894] "19001" "19001" "19001" "19001" ...
##  $ nombre_municipio: chr [1:3894] "Popayán" "Popayán" "Popayán" "Popayán" ...
##  $ Sexo            : chr [1:3894] "F" "F" "F" "F" ...
##  $ Fuente          : chr [1:3894] "RIPS" "RIPS" "RIPS" "RIPS" ...
##  $ anio            : int [1:3894] 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 ...
##  $ casos           : num [1:3894] 248 493 1174 2230 3394 ...
##  $ Codigo          : chr [1:3894] "19" "19" "19" "19" ...
##  $ Departamento    : chr [1:3894] "Cauca" "Cauca" "Cauca" "Cauca" ...
dplyr::glimpse(base_final_grafico)  # estructura como tibble
## Rows: 3,894
## Columns: 8
## $ codigo_municipio <chr> "19001", "19001", "19001", "19001", "19001", "19001",…
## $ nombre_municipio <chr> "Popayán", "Popayán", "Popayán", "Popayán", "Popayán"…
## $ Sexo             <chr> "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F"…
## $ Fuente           <chr> "RIPS", "RIPS", "RIPS", "RIPS", "RIPS", "RIPS", "RIPS…
## $ anio             <int> 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,…
## $ casos            <dbl> 248, 493, 1174, 2230, 3394, 4667, 6774, 8722, 11429, …
## $ Codigo           <chr> "19", "19", "19", "19", "19", "19", "19", "19", "19",…
## $ Departamento     <chr> "Cauca", "Cauca", "Cauca", "Cauca", "Cauca", "Cauca",…
dim(base_final_grafico)         # (filas, columnas)
## [1] 3894    8
nrow(base_final_grafico)        # filas
## [1] 3894
ncol(base_final_grafico)        # columnas
## [1] 8
names(base_final_grafico)       # nombres de variables
## [1] "codigo_municipio" "nombre_municipio" "Sexo"             "Fuente"          
## [5] "anio"             "casos"            "Codigo"           "Departamento"
# Vistas rápidas
head(base_final_grafico)        # 6 primeras
## # A tibble: 6 × 8
##   codigo_municipio nombre_municipio Sexo  Fuente  anio casos Codigo Departamento
##   <chr>            <chr>            <chr> <chr>  <int> <dbl> <chr>  <chr>       
## 1 19001            Popayán          F     RIPS    2009   248 19     Cauca       
## 2 19001            Popayán          F     RIPS    2010   493 19     Cauca       
## 3 19001            Popayán          F     RIPS    2011  1174 19     Cauca       
## 4 19001            Popayán          F     RIPS    2012  2230 19     Cauca       
## 5 19001            Popayán          F     RIPS    2013  3394 19     Cauca       
## 6 19001            Popayán          F     RIPS    2014  4667 19     Cauca
head(base_final_grafico, 10)    # 10 primeras
## # A tibble: 10 × 8
##    codigo_municipio nombre_municipio Sexo  Fuente  anio casos Codigo
##    <chr>            <chr>            <chr> <chr>  <int> <dbl> <chr> 
##  1 19001            Popayán          F     RIPS    2009   248 19    
##  2 19001            Popayán          F     RIPS    2010   493 19    
##  3 19001            Popayán          F     RIPS    2011  1174 19    
##  4 19001            Popayán          F     RIPS    2012  2230 19    
##  5 19001            Popayán          F     RIPS    2013  3394 19    
##  6 19001            Popayán          F     RIPS    2014  4667 19    
##  7 19001            Popayán          F     RIPS    2015  6774 19    
##  8 19001            Popayán          F     RIPS    2016  8722 19    
##  9 19001            Popayán          F     RIPS    2017 11429 19    
## 10 19001            Popayán          F     RIPS    2018 13820 19    
## # ℹ 1 more variable: Departamento <chr>
tail(base_final_grafico)        # 6 últimas
## # A tibble: 6 × 8
##   codigo_municipio nombre_municipio Sexo  Fuente  anio casos Codigo Departamento
##   <chr>            <chr>            <chr> <chr>  <int> <dbl> <chr>  <chr>       
## 1 76895            Zarzal           M     RIPS    2014   376 76     Valle       
## 2 76895            Zarzal           M     RIPS    2015   538 76     Valle       
## 3 76895            Zarzal           M     RIPS    2016   640 76     Valle       
## 4 76895            Zarzal           M     RIPS    2017   897 76     Valle       
## 5 76895            Zarzal           M     RIPS    2018  1066 76     Valle       
## 6 76895            Zarzal           M     RIPS    2019  1201 76     Valle
# Resumen para todas las variables numéricas
base_final_grafico %>%
  dplyr::summarise(
    dplyr::across(
      where(is.numeric),
      list(
        n       = ~sum(!is.na(.)),
        na      = ~sum(is.na(.)),
        media   = ~mean(., na.rm = TRUE),
        sd      = ~sd(., na.rm = TRUE),
        min     = ~min(., na.rm = TRUE),
        q25     = ~quantile(., 0.25, na.rm = TRUE),
        mediana = ~median(., na.rm = TRUE),
        q75     = ~quantile(., 0.75, na.rm = TRUE),
        max     = ~max(., na.rm = TRUE)
      ),
      .names = "{.col}__{.fn}"
    )
  )
## # A tibble: 1 × 18
##   anio__n anio__na anio__media anio__sd anio__min anio__q25 anio__mediana
##     <int>    <int>       <dbl>    <dbl>     <int>     <dbl>         <dbl>
## 1    3894        0        2014     3.16      2009      2011          2014
## # ℹ 11 more variables: anio__q75 <dbl>, anio__max <int>, casos__n <int>,
## #   casos__na <int>, casos__media <dbl>, casos__sd <dbl>, casos__min <dbl>,
## #   casos__q25 <dbl>, casos__mediana <dbl>, casos__q75 <dbl>, casos__max <dbl>
# NA por variable (tabla tidy)
tibble::tibble(variable = names(base_final_grafico)) %>%
  dplyr::mutate(
    n  = purrr::map_int(variable, ~sum(!is.na(base_final_grafico[[.x]]))),
    na = purrr::map_int(variable, ~sum( is.na(base_final_grafico[[.x]]))),
    prop_na = round(na / (n + na), 3)
  )
## # A tibble: 8 × 4
##   variable             n    na prop_na
##   <chr>            <int> <int>   <dbl>
## 1 codigo_municipio  3894     0   0    
## 2 nombre_municipio  3894     0   0    
## 3 Sexo              3894     0   0    
## 4 Fuente            3894     0   0    
## 5 anio              3894     0   0    
## 6 casos             2661  1233   0.317
## 7 Codigo            3894     0   0    
## 8 Departamento      3894     0   0
# Resúmenes ejemplo (solo si existen esas columnas)
if ("casos" %in% names(base_final_grafico)) {
  base_final_grafico %>%
    dplyr::summarise(
      n_registros   = dplyr::n(),
      total_casos   = sum(casos, na.rm = TRUE),
      media_casos   = mean(casos, na.rm = TRUE),
      sd_casos      = sd(casos, na.rm = TRUE),
      mediana_casos = median(casos, na.rm = TRUE)
    )
}
## # A tibble: 1 × 5
##   n_registros total_casos media_casos sd_casos mediana_casos
##         <int>       <dbl>       <dbl>    <dbl>         <dbl>
## 1        3894     4104207       1542.   12935.           116
if (all(c("Departamento","anio","casos") %in% names(base_final_grafico))) {
  base_final_grafico %>%
    dplyr::group_by(Departamento, anio) %>%
    dplyr::summarise(total_casos = sum(casos, na.rm = TRUE), .groups = "drop") %>%
    dplyr::arrange(Departamento, anio)
}
## # A tibble: 44 × 3
##    Departamento  anio total_casos
##    <chr>        <int>       <dbl>
##  1 Cauca         2009        1765
##  2 Cauca         2010        3937
##  3 Cauca         2011        7226
##  4 Cauca         2012       14603
##  5 Cauca         2013       22762
##  6 Cauca         2014       32620
##  7 Cauca         2015       41642
##  8 Cauca         2016       49071
##  9 Cauca         2017       62175
## 10 Cauca         2018       78855
## # ℹ 34 more rows
# PartO de mi base larga ya cargada: base_final_grafico
stopifnot(exists("base_final_grafico"))

# Alias con el nombre que espera la guía
base_final <- tibble::as_tibble(base_final_grafico)

# Chequeos útiles
dplyr::distinct(base_final, Departamento) %>% dplyr::arrange(Departamento)
## # A tibble: 4 × 1
##   Departamento
##   <chr>       
## 1 Cauca       
## 2 Choco       
## 3 Narino      
## 4 Valle
dplyr::distinct(base_final, Sexo)
## # A tibble: 2 × 1
##   Sexo 
##   <chr>
## 1 F    
## 2 M
names(base_final)
## [1] "codigo_municipio" "nombre_municipio" "Sexo"             "Fuente"          
## [5] "anio"             "casos"            "Codigo"           "Departamento"
# La guía me solicita: una fila por municipio (Muni) y una columna por año.
# 1) Renombramos 'nombre_municipio' -> 'Muni' y nos quedamos con lo necesario
base_final <- base_final %>%
  dplyr::rename(Muni = nombre_municipio) %>%
  dplyr::select(Departamento, Sexo, Muni, anio, casos)

# 2) Aseguro tipos y agregamos por si hay duplicados
base_final <- base_final %>%
  dplyr::mutate(anio = as.integer(anio)) %>%
  dplyr::group_by(Departamento, Sexo, Muni, anio) %>%
  dplyr::summarise(casos = sum(casos, na.rm = TRUE), .groups = "drop")

# 3) Pivot a ancho: una columna por año
base_final <- base_final %>%
  tidyr::pivot_wider(
    names_from = anio, values_from = casos,
    values_fn = sum, values_fill = 0
  ) %>%
  dplyr::arrange(Departamento, Muni)

# 4) Ordeno columnas: (Departamento, Sexo, Muni, 2009..2019) si existen
years <- as.character(2009:2019)
year_cols <- intersect(years, names(base_final))
base_final <- base_final[, c(setdiff(names(base_final), years), year_cols)]
# La guía: filtrar Valle del Cauca y Sexo F
# (Hacemos el filtro robusto a mayúsculas/minúsculas)
base_graficos <- base_final %>%
  dplyr::filter(stringr::str_detect(Departamento, stringr::regex("^valle", ignore_case = TRUE)),
                Sexo == "F") %>%
  dplyr::select(Muni, dplyr::all_of(year_cols))

# Si faltara algún año en la base, lo creo con 0 para que no falle:
faltan <- setdiff(years, names(base_graficos))
for (y in faltan) base_graficos[[y]] <- 0L
base_graficos <- base_graficos[, c("Muni", years)]
# Adapto al bloque de la guía:
# Transponemos para tener los años en filas y municipios en columnas
bg_t <- as.data.frame(t(base_graficos), stringsAsFactors = FALSE)

# La primera "fila" de bg_t (que es la columna 'Muni' original) pasa a ser nombres de columnas
colnames(bg_t) <- bg_t[1, ]
bg_t <- bg_t[-1, , drop = FALSE]

# Creo columna 'anio' desde los rownames
bg_t$anio <- rownames(bg_t)

# Convierto a numéricas las columnas de municipios; 'anio' a entero
num_cols <- setdiff(names(bg_t), "anio")
bg_t[num_cols] <- lapply(bg_t[num_cols], function(x) suppressWarnings(as.numeric(x)))
bg_t$anio <- as.integer(bg_t$anio)
rownames(bg_t) <- NULL

# Dejo el objeto final con el nombre de la guía
base_graficos <- bg_t

# Vista rápida
head(base_graficos)
##   Alcalá Andalucía Ansermanuevo Argelia Bolívar Buenaventura Bugalagrande
## 1      3        11            1       0       0           73            4
## 2      4        38            2       0       0          226            8
## 3      0       138           14       0       3          773           20
## 4      6       226            0       1       7         1946          248
## 5     16       349           17      14       9         2830          380
## 6     67       496           48       0      19         4092          905
##   Caicedonia  Cali Calima Candelaria Cartago Dagua El Cairo El Cerrito El Dovio
## 1        127  2397      0         64     144     2        0         19        0
## 2        208  6012      0        110     265     8        0         29        0
## 3        385 14720      2        233     464    77        0        136        9
## 4        744 28312      3       1270     772     0        7        213        0
## 5        997 40138     14       1414    1266    78       11        657        0
## 6       1363 54700     34       1606    1706    83       61        854       33
##   El Águila Florida Ginebra Guacarí Guadalajara De Buga Jamundí La Cumbre
## 1        12       7       0       0                  51      30         0
## 2        15      25       0      14                 109      42         0
## 3         0      60      15      21                 424     126         1
## 4        18     146      25      46                 831     241         3
## 5         0     200      44      76                1190     400         0
## 6        19     571      74     117                1751     535         0
##   La Unión La Victoria Obando Palmira Pradera Restrepo Riofrío Roldanillo
## 1        0           2      2     130      43        4      12         39
## 2        0           0      0     337      83        8      23         67
## 3        0           0      5     638     151       19      71         83
## 4       16           0      0    1444     393       62     221        107
## 5       66           3     18    1975     491       70     310        126
## 6      136          15     88    2747     659       79     389        166
##   San Pedro Sevilla Toro Trujillo Tuluá Ulloa Versalles Vijes Yotoco Yumbo
## 1         0      16    3        0   199    12         0     0      0    31
## 2         0      56   11       10   422    18         0     7     11    88
## 3         0     142   36       19  1119    23         1    30    118   222
## 4         0     260   49       37  2281    29         0    89    211   470
## 5        42     431   70       74  3292    34         0   120    271  1570
## 6        71     635  121       97  4405    35         0   147    375  2089
##   Zarzal anio
## 1     61 2009
## 2     80 2010
## 3    122 2011
## 4    210 2012
## 5    324 2013
## 6    454 2014
str(base_graficos)
## 'data.frame':    11 obs. of  43 variables:
##  $ Alcalá             : num  3 4 0 6 16 67 110 168 205 221 ...
##  $ Andalucía          : num  11 38 138 226 349 496 597 686 770 813 ...
##  $ Ansermanuevo       : num  1 2 14 0 17 48 118 138 178 377 ...
##  $ Argelia            : num  0 0 0 1 14 0 17 0 20 24 ...
##  $ Bolívar            : num  0 0 3 7 9 19 30 32 35 0 ...
##  $ Buenaventura       : num  73 226 773 1946 2830 ...
##  $ Bugalagrande       : num  4 8 20 248 380 ...
##  $ Caicedonia         : num  127 208 385 744 997 ...
##  $ Cali               : num  2397 6012 14720 28312 40138 ...
##  $ Calima             : num  0 0 2 3 14 34 41 69 100 302 ...
##  $ Candelaria         : num  64 110 233 1270 1414 ...
##  $ Cartago            : num  144 265 464 772 1266 ...
##  $ Dagua              : num  2 8 77 0 78 83 90 91 133 377 ...
##  $ El Cairo           : num  0 0 0 7 11 61 72 84 89 0 ...
##  $ El Cerrito         : num  19 29 136 213 657 ...
##  $ El Dovio           : num  0 0 9 0 0 33 48 0 58 66 ...
##  $ El Águila          : num  12 15 0 18 0 19 0 20 28 63 ...
##  $ Florida            : num  7 25 60 146 200 ...
##  $ Ginebra            : num  0 0 15 25 44 74 105 144 316 459 ...
##  $ Guacarí            : num  0 14 21 46 76 117 154 231 373 420 ...
##  $ Guadalajara De Buga: num  51 109 424 831 1190 ...
##  $ Jamundí            : num  30 42 126 241 400 ...
##  $ La Cumbre          : num  0 0 1 3 0 0 0 0 0 54 ...
##  $ La Unión           : num  0 0 0 16 66 136 189 212 274 372 ...
##  $ La Victoria        : num  2 0 0 0 3 15 0 20 39 87 ...
##  $ Obando             : num  2 0 5 0 18 88 181 275 308 321 ...
##  $ Palmira            : num  130 337 638 1444 1975 ...
##  $ Pradera            : num  43 83 151 393 491 ...
##  $ Restrepo           : num  4 8 19 62 70 79 119 133 226 400 ...
##  $ Riofrío            : num  12 23 71 221 310 389 419 452 497 720 ...
##  $ Roldanillo         : num  39 67 83 107 126 166 214 225 329 482 ...
##  $ San Pedro          : num  0 0 0 0 42 71 95 148 173 273 ...
##  $ Sevilla            : num  16 56 142 260 431 ...
##  $ Toro               : num  3 11 36 49 70 121 161 213 258 322 ...
##  $ Trujillo           : num  0 10 19 37 74 97 116 134 188 307 ...
##  $ Tuluá              : num  199 422 1119 2281 3292 ...
##  $ Ulloa              : num  12 18 23 29 34 35 0 0 46 113 ...
##  $ Versalles          : num  0 0 1 0 0 0 0 0 2 15 ...
##  $ Vijes              : num  0 7 30 89 120 147 194 199 200 223 ...
##  $ Yotoco             : num  0 11 118 211 271 375 433 541 604 645 ...
##  $ Yumbo              : num  31 88 222 470 1570 ...
##  $ Zarzal             : num  61 80 122 210 324 ...
##  $ anio               : int  2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 ...
# Reemplazo "Cali" por el municipio que tengo en columnas
plot(base_graficos$anio, base_graficos[["Cali"]], type = "l",
     xlab = "Año", ylab = "Casos", main = "Cali (F) - Valle del Cauca")

x <- base_graficos$anio
y <- base_graficos[["Cali"]]

cambio_abs <- y[length(y)] - y[1]
cambio_rel <- 100 * cambio_abs / y[1]
tasa_media_anual <- (y[length(y)]/y[1])^(1/(length(y)-1)) - 1
data.frame(
  anio_inicial = x[1], casos_inicial = y[1],
  anio_final   = x[length(x)], casos_final = y[length(y)],
  cambio_abs, cambio_rel = round(cambio_rel, 1),
  tasa_media_anual = scales::percent(tasa_media_anual)
)
##   anio_inicial casos_inicial anio_final casos_final cambio_abs cambio_rel
## 1         2009          2397       2019      112346     109949     4586.9
##   tasa_media_anual
## 1              47%
plot(x, y/1000, type="o", xlab="Año", ylab="Casos (miles)",
     main="Cali (F) - Valle del Cauca")
grid()

plot_muni <- function(m){
  y <- base_graficos[[m]]
  plot(x, y, type="o", xlab="Año", ylab="Casos",
       main=paste(m, "(F) - Valle del Cauca"))
  grid()
}
# Ejemplos:
plot_muni("Cali")

# plot_muni("Palmira")
# Elijo municipio y preparo vectores
muni <- "Cali"                            # <- cámbialo si quieres
stopifnot(muni %in% names(base_graficos))

x <- base_graficos$anio                   # años (eje X “correcto”)
y <- base_graficos[[muni]]                # serie del municipio
titulo <- paste(muni, "(F) - Valle del Cauca")
plot(base_graficos[[muni]], type = "l",
     main = "Número de atenciones a mujeres por diagnósticos relacionados a VIH")

plot(x, y, type = "l", xlab = "Año", ylab = "Casos", main = titulo)
grid()

op <- options(scipen = 999)   # evita notación científica
on.exit(options(op), add = TRUE)

plot(x, y, type = "l", xlab = "Año", ylab = "Casos", main = titulo,
     xaxt = "n", yaxt = "n")
axis(1, at = x, labels = x)
tcks <- pretty(y)
axis(2, at = tcks, labels = format(tcks, big.mark = ".", decimal.mark = ","))
grid(); box()

plot(x, y/1000, type = "o", xlab = "Año", ylab = "Casos (miles)", main = titulo)
grid()

is.numeric(y)         # debe ser TRUE
## [1] TRUE
summary(y)            # revisa rangos
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    2397   21516   54700   53958   82149  112346
any(diff(y) < 0)      # FALSE = serie estrictamente ascendente
## [1] FALSE
plot_muni_pretty <- function(m, tipo = "l"){
  stopifnot(m %in% names(base_graficos))
  yy <- base_graficos[[m]]
  op <- options(scipen = 999); on.exit(options(op), add = TRUE)
  plot(x, yy, type = tipo, xlab = "Año", ylab = "Casos",
       main = paste(m, "(F) - Valle del Cauca"), xaxt = "n", yaxt = "n")
  axis(1, at = x, labels = x)
  tcks <- pretty(yy)
  axis(2, at = tcks, labels = format(tcks, big.mark = ".", decimal.mark = ","))
  grid(); box()
}
# Ejemplos:
# plot_muni_pretty("Cali", "o")
# plot_muni_pretty("Palmira", "s")
# Municipio (usa el que ya vienes usando)
# muni <- "Cali"

y <- base_graficos[[muni]]
x <- base_graficos$anio

# Estadísticos
min_val <- min(y, na.rm = TRUE);  min_year <- x[which.min(y)]
q1  <- as.numeric(quantile(y, 0.25, names = FALSE))
med <- as.numeric(quantile(y, 0.50, names = FALSE))
q3  <- as.numeric(quantile(y, 0.75, names = FALSE))
q1_year  <- x[which.min(abs(y - q1))]
med_year <- x[which.min(abs(y - med))]
q3_year  <- x[which.min(abs(y - q3))]
max_val <- max(y, na.rm = TRUE);  max_year <- x[which.max(y)]
mean_val <- mean(y); sd_y <- sd(y)
cv <- sd_y / mean_val
IQR_y <- IQR(y)
rango <- max_val - min_val
cambio_abs <- y[length(y)] - y[1]
cambio_rel <- 100 * cambio_abs / y[1]
tasa_media_anual <- 100 * ((y[length(y)]/y[1])^(1/(length(y)-1)) - 1)

# Formateo bonito (puntos para miles, coma para decimales)
fmt_num <- function(v, dig = 0){
  format(round(v, dig), big.mark = ".", decimal.mark = ",")
}
fmt_pct <- function(v, dig = 1){
  paste0(format(round(v, dig), big.mark = ".", decimal.mark = ","), "%")
}

tabla <- tibble::tibble(
  Medida = c(
    "Mínimo", "Q1 (25%)", "Mediana (50%)", "Media", "Q3 (75%)", "Máximo",
    "Rango (Máx − Mín)", "IQR (Q3 − Q1)", "Desviación estándar",
    "Coeficiente de variación", "Cambio absoluto (último − primero)",
    "Cambio relativo", "Crecimiento medio anual"
  ),
  Valor = c(
    fmt_num(min_val), fmt_num(q1), fmt_num(med), fmt_num(mean_val, 1),
    fmt_num(q3), fmt_num(max_val), fmt_num(rango), fmt_num(IQR_y),
    fmt_num(sd_y, 1), fmt_pct(cv*100), fmt_num(cambio_abs),
    fmt_pct(cambio_rel), fmt_pct(tasa_media_anual)
  ),
  `Año relacionado` = c(
    min_year, q1_year, med_year, NA, q3_year, max_year,
    NA, NA, NA, NA, NA, NA, NA
  ),
  Explicación = c(
    "Año con menor número de atenciones",
    "25% de los años tuvieron ≤ este valor",
    "50% de los años quedaron por debajo (año típico)",
    "Promedio de todos los años",
    "75% de los años tuvieron ≤ este valor",
    "Año con mayor número de atenciones",
    "Amplitud total de la serie (variación total)",
    "Variabilidad del 50% central (Q1–Q3)",
    "Dispersión promedio alrededor de la media",
    "Variabilidad relativa (SD/Media × 100)",
    "Diferencia entre último y primer año",
    "Incremento total respecto al primer año",
    "Crecimiento compuesto promedio por año"
  )
)

knitr::kable(
  tabla,
  caption = paste("Resumen descriptivo de casos por año —", muni, "(F) - Valle del Cauca")
)
Resumen descriptivo de casos por año — Cali (F) - Valle del Cauca
Medida Valor Año relacionado Explicación
Mínimo 2.397 2009 Año con menor número de atenciones
Q1 (25%) 21.516 2011 25% de los años tuvieron ≤ este valor
Mediana (50%) 54.700 2014 50% de los años quedaron por debajo (año típico)
Media 53.957,8 NA Promedio de todos los años
Q3 (75%) 82.149 2016 75% de los años tuvieron ≤ este valor
Máximo 112.346 2019 Año con mayor número de atenciones
Rango (Máx − Mín) 109.949 NA Amplitud total de la serie (variación total)
IQR (Q3 − Q1) 60.633 NA Variabilidad del 50% central (Q1–Q3)
Desviación estándar 38.937,4 NA Dispersión promedio alrededor de la media
Coeficiente de variación 72,2% NA Variabilidad relativa (SD/Media × 100)
Cambio absoluto (último − primero) 109.949 NA Diferencia entre último y primer año
Cambio relativo 4.586,9% NA Incremento total respecto al primer año
Crecimiento medio anual 46,9% NA Crecimiento compuesto promedio por año
stopifnot(exists("base_graficos"), exists("muni"), muni %in% names(base_graficos))

anio <- base_graficos$anio
y    <- base_graficos[[muni]]

# Cambios vs. año previo
prev       <- c(NA, head(y, -1))
delta_abs  <- y - prev
delta_pct  <- (y / prev - 1) * 100
delta_pct[1] <- NA
delta_pct[is.infinite(delta_pct)] <- NA

total <- sum(y)

# Tabla base numérica
tab_num <- tibble::tibble(
  Año = anio,
  Casos = y,
  `Δ abs. (vs. año previo)` = delta_abs,
  `Δ % (vs. año previo)` = delta_pct,
  `Acumulado` = cumsum(y),
  `% del total` = 100 * y / total
)

# Formateo bonito
fmt_num <- function(v, dig = 0) format(round(v, dig), big.mark = ".", decimal.mark = ",")
fmt_pct <- function(v, dig = 1) ifelse(is.na(v), "–",
                                       paste0(format(round(v, dig), big.mark = ".", decimal.mark = ","), "%"))

tab_fmt <- tab_num %>%
  dplyr::mutate(
    Año = as.character(Año),                 # <- clave para que bind_rows no falle
    Casos = fmt_num(Casos),
    `Δ abs. (vs. año previo)` = ifelse(is.na(`Δ abs. (vs. año previo)`), "–",
                                       fmt_num(`Δ abs. (vs. año previo)`)),
    `Δ % (vs. año previo)` = fmt_pct(`Δ % (vs. año previo)`),
    `Acumulado` = fmt_num(`Acumulado`),
    `% del total` = fmt_pct(`% del total`)
  )

# Fila TOTAL (mismos tipos que tab_fmt)
fila_total <- tibble::tibble(
  Año = "TOTAL",
  Casos = fmt_num(total),
  `Δ abs. (vs. año previo)` = "",
  `Δ % (vs. año previo)` = "",
  `Acumulado` = fmt_num(total),
  `% del total` = "100%"
)

tabla_final <- dplyr::bind_rows(tab_fmt, fila_total)

knitr::kable(
  tabla_final,
  caption = paste("Casos por año —", muni, "(F) - Valle del Cauca")
)
Casos por año — Cali (F) - Valle del Cauca
Año Casos Δ abs. (vs. año previo) Δ % (vs. año previo) Acumulado % del total
2009 2.397 2.397 0,4%
2010 6.012 3.615 150,8% 8.409 1,0%
2011 14.720 8.708 144,8% 23.129 2,5%
2012 28.312 13.592 92,3% 51.441 4,8%
2013 40.138 11.826 41,8% 91.579 6,8%
2014 54.700 14.562 36,3% 146.279 9,2%
2015 66.082 11.382 20,8% 212.361 11,1%
2016 74.674 8.592 13,0% 287.035 12,6%
2017 89.624 14.950 20,0% 376.659 15,1%
2018 104.531 14.907 16,6% 481.190 17,6%
2019 112.346 7.815 7,5% 593.536 18,9%
TOTAL 593.536 593.536 100%
library(ggplot2)

# Uso el municipio que ya vengo trabajando
# muni <- "Cali"

# Data frame largo para ggplot2
df_muni <- tibble::tibble(
  anio  = base_graficos$anio,
  casos = base_graficos[[muni]]
)
stopifnot(is.numeric(df_muni$casos))
ggplot(df_muni, aes(x = anio, y = casos)) +
  geom_line() +
  labs(title = paste("Línea —", muni, "(F) - Valle del Cauca"),
       x = "Año", y = "Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))

ggplot(df_muni, aes(x = anio, y = casos)) +
  geom_step() +
  labs(title = paste("Escaleras —", muni, "(F) - Valle del Cauca"),
       x = "Año", y = "Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))

ggplot(df_muni, aes(x = anio, y = casos)) +
  geom_point(size = 2) +
  labs(title = paste("Puntos —", muni, "(F) - Valle del Cauca"),
       x = "Año", y = "Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))

ggplot(df_muni, aes(x = anio, y = casos)) +
  geom_line() +
  geom_point(size = 2) +
  labs(title = paste("Puntos y líneas —", muni, "(F) - Valle del Cauca"),
       x = "Año", y = "Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))

ggplot(df_muni, aes(x = anio, y = casos)) +
  geom_point(size = 2) +
  geom_line() +
  labs(title = paste("Puntos encima de la línea —", muni, "(F) - Valle del Cauca"),
       x = "Año", y = "Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))

ggplot(df_muni, aes(x = anio, y = casos)) +
  geom_col() +
  labs(title = paste("Barras por año (análogo a type = 'h') —", muni),
       x = "Año", y = "Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))

ggplot(df_muni, aes(x = casos)) +
  geom_histogram(bins = 10, boundary = 0, closed = "left") +
  labs(title = paste("Histograma de la distribución de casos —", muni),
       x = "Casos", y = "Frecuencia") +
  scale_x_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","))

muni <- "Palmira"   # por ejemplo
df_muni <- tibble::tibble(anio = base_graficos$anio, casos = base_graficos[[muni]])
# Línea
ggplot(df_muni, aes(anio, casos)) +
  geom_line() +
  labs(title = paste("Línea —", muni), x = "Año", y = "Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark=".", decimal_mark=","))

# Escaleras
ggplot(df_muni, aes(anio, casos)) + geom_step() + labs(title=paste("Escaleras —", muni), x="Año", y="Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark=".", decimal_mark=","))

# Puntos
ggplot(df_muni, aes(anio, casos)) + geom_point(size=2) + labs(title=paste("Puntos —", muni), x="Año", y="Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark=".", decimal_mark=","))

# Puntos + líneas
ggplot(df_muni, aes(anio, casos)) + geom_line() + geom_point(size=2) +
  labs(title=paste("Puntos y líneas —", muni), x="Año", y="Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark=".", decimal_mark=","))

# Barras por año (análogo a type='h')
ggplot(df_muni, aes(anio, casos)) + geom_col() +
  labs(title=paste("Barras por año —", muni), x="Año", y="Casos") +
  scale_x_continuous(breaks = df_muni$anio) +
  scale_y_continuous(labels = scales::label_number(big.mark=".", decimal_mark=","))

# uso los objetos que ya tienes: x = base_graficos$anio, y = base_graficos[[muni]]

op <- options(scipen = 999); on.exit(options(op), add = TRUE)
plot(x, y, type = "h", lwd = 6, lend = "butt",
     xaxt = "n", yaxt = "n",
     xlab = "Año", ylab = "Casos",
     main = paste("Barras por año —", muni, "(F) - Valle del Cauca)"))
axis(1, at = x, labels = x)
ticks <- pretty(y)
axis(2, at = ticks, labels = format(ticks, big.mark = ".", decimal.mark = ","))
grid(); box()

hist(y, breaks = 6,
     main = paste("Histograma de la distribución de casos —", muni),
     xlab = "Casos", ylab = "Frecuencia")

library(ggplot2)
ggplot(tibble::tibble(casos = y), aes(casos)) +
  geom_histogram(bins = 6, boundary = 0, closed = "left") +
  labs(title = paste("Histograma de la distribución de casos —", muni),
       x = "Casos", y = "Frecuencia") +
  scale_x_continuous(labels = scales::label_number(big.mark=".", decimal.mark=","))

library(tidyr); library(dplyr)

# base_final tiene: Departamento, Sexo, Muni, columnas 2009..2019
datos_long <- base_final %>%
  pivot_longer(
    cols = matches("^20\\d{2}$"),   # toma columnas 2009..2019
    names_to  = "Año",
    values_to = "Valor"
  ) %>%
  mutate(Año = as.integer(Año))
dplyr::glimpse(datos_long)
## Rows: 3,894
## Columns: 5
## $ Departamento <chr> "Cauca", "Cauca", "Cauca", "Cauca", "Cauca", "Cauca", "Ca…
## $ Sexo         <chr> "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "M…
## $ Muni         <chr> "Almaguer", "Almaguer", "Almaguer", "Almaguer", "Almaguer…
## $ Año          <int> 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 201…
## $ Valor        <dbl> 0, 0, 0, 0, 2, 0, 3, 0, 8, 0, 0, 2, 24, 36, 58, 85, 105, …
library(dplyr); library(stringr)

# 1) ¿Qué hay para 2019, F, Valle?
diag <- datos_long %>%
  filter(Año == 2019, Sexo == "F",
         str_detect(Departamento, regex("valle", ignore_case = TRUE))) %>%
  summarise(
    n_filas         = n(),
    con_valor       = sum(!is.na(Valor)),
    positivos       = sum(Valor > 0, na.rm = TRUE),
    muni_distintos  = n_distinct(Muni)
  )
diag
## # A tibble: 1 × 4
##   n_filas con_valor positivos muni_distintos
##     <int>     <int>     <int>          <int>
## 1      42        42        40             42
# 2) ¿Cómo se llaman exactamente los municipios?
munis_valle_2019 <- datos_long %>%
  filter(Año == 2019, Sexo == "F",
         str_detect(Departamento, regex("valle", ignore_case = TRUE))) %>%
  distinct(Muni) %>% arrange(Muni)
munis_valle_2019
## # A tibble: 42 × 1
##    Muni        
##    <chr>       
##  1 Alcalá      
##  2 Andalucía   
##  3 Ansermanuevo
##  4 Argelia     
##  5 Bolívar     
##  6 Buenaventura
##  7 Bugalagrande
##  8 Caicedonia  
##  9 Cali        
## 10 Calima      
## # ℹ 32 more rows
library(ggplot2)

# Filtro 2019, F, Valle y EXCLUIMOS 'Cali' (considerando dos variantes de nombre)
df_v19 <- datos_long %>%
  filter(Año == 2019, Sexo == "F",
         str_detect(Departamento, regex("valle", ignore_case = TRUE))) %>%
  filter(!is.na(Valor)) %>%
  filter(!str_detect(Muni, regex("^cali$|santiago\\s+de\\s+cali", ignore_case = TRUE)))

# Si no hay datos, se pone aclaracion
if (nrow(df_v19) == 0) {
  message("⚠️ No hay datos para 2019 (F) en Valle sin Cali. Revisa los nombres en el chunk de diagnóstico.")
} else {
  # Binwidth seguro: si IQR es 0/NA, usamos fallback de 10 bins sobre el rango
  iqr <- IQR(df_v19$Valor, na.rm = TRUE)
  rng <- range(df_v19$Valor, na.rm = TRUE)
  n   <- nrow(df_v19)
  bw_fd <- if (n >= 2 && is.finite(iqr) && iqr > 0) 2 * iqr / (n^(1/3)) else NA_real_
  bw <- if (!is.na(bw_fd) && is.finite(bw_fd) && bw_fd > 0) bw_fd else max(1, diff(rng) / 10)

  ggplot(df_v19, aes(x = Valor)) +
    geom_histogram(binwidth = bw, boundary = 0, closed = "left",
                   fill = "lightblue", color = "grey30") +
    labs(title = "Histograma — Municipios del Valle (sin Cali), 2019 (F)",
         x = "Atenciones", y = "Frecuencia") +
    scale_x_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ",")) +
    theme_minimal()
}

# Control: mismo filtro pero SIN excluir Cali, y verifico visualmente
df_v19_all <- datos_long %>%
  filter(Año == 2019, Sexo == "F",
         str_detect(Departamento, regex("valle", ignore_case = TRUE))) %>%
  filter(!is.na(Valor))

if (nrow(df_v19_all) > 0) {
  ggplot(df_v19_all, aes(x = Valor)) +
    geom_histogram(bins = 15, boundary = 0, closed = "left",
                   fill = "skyblue", color = "grey30") +
    labs(title = "Histograma (control) — Municipios del Valle (con Cali), 2019 (F)",
         x = "Atenciones", y = "Frecuencia") +
    scale_x_continuous(labels = scales::label_number(big.mark=".", decimal.mark=",")) +
    theme_minimal()
} else {
  message("⚠️ No hay filas para 2019 (F) en Valle ni siquiera incluyendo Cali.")
}

library(dplyr); library(stringr); library(ggplot2)

# 1) Normalizo espacios por si hay dobles o finales
datos_long <- datos_long %>%
  mutate(
    Departamento = stringr::str_squish(Departamento),
    Muni         = stringr::str_squish(Muni)
  )

# 2) Miro cómo se llama realmente "Cali" y su departamento
vista_cali <- datos_long %>%
  filter(Sexo == "F", str_detect(Muni, regex("cali", ignore_case = TRUE))) %>%
  distinct(Muni, Departamento) %>%
  arrange(Muni)
print(vista_cali, n = nrow(vista_cali))
## # A tibble: 2 × 2
##   Muni   Departamento
##   <chr>  <chr>       
## 1 Cali   Valle       
## 2 Calima Valle
# 3) Filtro flexible para Valle y Cali
df_cali <- datos_long %>%
  filter(
    Sexo == "F",
    str_detect(Departamento, regex("valle(\\s+del\\s+cauca)?", ignore_case = TRUE)),
    str_detect(Muni, regex("^cali$|santiago\\s+de\\s+cali", ignore_case = TRUE))
  ) %>%
  group_by(Año) %>%
  summarise(Valor = sum(Valor, na.rm = TRUE), .groups = "drop") %>%
  arrange(Año)

if (nrow(df_cali) == 0) {
  message("⚠️ El filtro sigue sin devolver filas. Revisa la tabla 'vista_cali' impresa arriba ",
          "para ver el nombre exacto de Muni y Departamento y ajústalo en el regex.")
} else {
  ggplot(df_cali, aes(x = Año, y = Valor)) +
    geom_line() +
    geom_point(size = 2) +
    labs(title = "Cali (F) — Línea con puntos",
         x = "Año", y = "Atenciones") +
    scale_x_continuous(breaks = df_cali$Año) +
    scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ",")) +
    theme_minimal()
}

ggplot(df_cali, aes(Año, Valor)) +
  geom_step() +
  labs(title = "Cali (F) — Escaleras", x = "Año", y = "Atenciones") +
  scale_x_continuous(breaks = df_cali$Año) +
  scale_y_continuous(labels = scales::label_number(big.mark=".", decimal.mark=",")) +
  theme_minimal()

ggplot(df_cali, aes(Año, Valor)) +
  geom_point(size = 2) +
  labs(title = "Cali (F) — Puntos", x = "Año", y = "Atenciones") +
  scale_x_continuous(breaks = df_cali$Año) +
  scale_y_continuous(labels = scales::label_number(big.mark=".", decimal.mark=",")) +
  theme_minimal()

ggplot(df_cali, aes(Año, Valor)) +
  geom_col() +
  labs(title = "Cali (F) — Barras por año", x = "Año", y = "Atenciones") +
  scale_x_continuous(breaks = df_cali$Año) +
  scale_y_continuous(labels = scales::label_number(big.mark=".", decimal.mark=",")) +
  theme_minimal()

ggplot(df_cali, aes(Valor)) +
  geom_histogram(bins = 8, boundary = 0, closed = "left",
                 fill = "steelblue", color = "grey30") +
  labs(title = "Cali (F) — Histograma de la distribución (2009–2019)",
       x = "Atenciones", y = "Frecuencia") +
  scale_x_continuous(labels = scales::label_number(big.mark=".", decimal.mark=",")) +
  theme_minimal()

library(dplyr); library(ggplot2)

dist_abs_2015F <- datos_long %>%
  filter(Año == 2015, Sexo == "F") %>%
  filter(!is.na(Valor)) %>%              # “disponibles en los datos”
  distinct(Departamento, Muni) %>%       # 1 vez por municipio
  count(Departamento, name = "n_municipios") %>%
  arrange(desc(n_municipios))

dist_abs_2015F
## # A tibble: 4 × 2
##   Departamento n_municipios
##   <chr>               <int>
## 1 Narino                 64
## 2 Cauca                  42
## 3 Valle                  42
## 4 Choco                  29
ggplot(dist_abs_2015F, aes(x = Departamento, y = n_municipios)) +
  geom_col(fill = "royalblue4") +
  labs(title = "Distribución de los municipios por departamento (2015, F)",
       x = "Departamento", y = "Frecuencia") +
  theme_minimal()

dist_rel_2015F <- dist_abs_2015F %>%
  mutate(pct = 100 * n_municipios / sum(n_municipios))

dist_rel_2015F
## # A tibble: 4 × 3
##   Departamento n_municipios   pct
##   <chr>               <int> <dbl>
## 1 Narino                 64  36.2
## 2 Cauca                  42  23.7
## 3 Valle                  42  23.7
## 4 Choco                  29  16.4
ggplot(dist_rel_2015F, aes(x = Departamento, y = pct)) +
  geom_col(fill = "royalblue4") +
  labs(title = "Distribución relativa de municipios por departamento (2015, F)",
       x = "Departamento", y = "%") +
  scale_y_continuous(labels = function(x) paste0(x, "%")) +
  theme_minimal()

library(stringr)

# Normalizo espacios y unifico nombres de capitales
caps_df <- datos_long %>%
  mutate(
    Departamento = str_squish(Departamento),
    Muni = str_squish(Muni)
  ) %>%
  filter(Sexo == "F",
         str_detect(Muni, regex("^cali$|santiago\\s+de\\s+cali|popay[aá]n|^pasto$|quibd[oó]", ignore_case = TRUE))) %>%
  mutate(Capital = case_when(
    str_detect(Muni, regex("^cali$|santiago\\s+de\\s+cali", ignore_case = TRUE)) ~ "Cali",
    str_detect(Muni, regex("popay[aá]n", ignore_case = TRUE)) ~ "Popayán",
    str_detect(Muni, regex("^pasto$", ignore_case = TRUE)) ~ "Pasto",
    str_detect(Muni, regex("quibd[oó]", ignore_case = TRUE)) ~ "Quibdó",
    TRUE ~ Muni
  )) %>%
  filter(!is.na(Valor))

# ---- Opción A: Boxplot con TODOS los años (recomendado) ----
ggplot(caps_df, aes(x = Capital, y = Valor)) +
  geom_boxplot(fill = "lightblue", color = "navy") +
  labs(title = "Boxplot de atenciones por capitales de la región (todos los años, F)",
       x = "Ciudad capital", y = "Número de atenciones") +
  theme_minimal()

# ---- Opción B: si quiero mostrar SOLO 2015, uso puntos (no hay caja) ----
caps_2015 <- caps_df %>% filter(Año == 2015)

ggplot(caps_2015, aes(x = Capital, y = Valor)) +
  geom_point(size = 3, alpha = 0.8, color = "navy") +
  labs(title = "Atenciones en capitales de la región (2015, F)",
       x = "Ciudad capital", y = "Número de atenciones") +
  theme_minimal()

library(ggplot2)
dist_abs_2015F %>%
  ggplot(aes(x = reorder(Departamento, n_municipios), y = n_municipios)) +
  geom_col(fill = "royalblue4") +
  geom_text(aes(label = n_municipios), vjust = -0.25, size = 4) +
  labs(title = "Municipios por departamento (2015, F)",
       x = "Departamento", y = "Frecuencia") +
  theme_minimal() +
  coord_cartesian(ylim = c(0, max(dist_abs_2015F$n_municipios) * 1.1))

dist_rel_2015F %>%
  ggplot(aes(x = reorder(Departamento, pct), y = pct)) +
  geom_col(fill = "royalblue4") +
  geom_text(aes(label = paste0(round(pct,1), "%")),
            vjust = -0.25, size = 4) +
  labs(title = "Distribución relativa (2015, F)",
       x = "Departamento", y = "%") +
  theme_minimal() +
  coord_cartesian(ylim = c(0, max(dist_rel_2015F$pct) * 1.1))

library(dplyr)
resumen_caps <- caps_df %>%
  group_by(Capital) %>%
  summarise(
    n = n(),
    min   = min(Valor, na.rm = TRUE),
    q1    = quantile(Valor, .25, na.rm = TRUE),
    med   = median(Valor, na.rm = TRUE),
    mean  = mean(Valor, na.rm = TRUE),
    q3    = quantile(Valor, .75, na.rm = TRUE),
    max   = max(Valor, na.rm = TRUE),
    iqr   = IQR(Valor, na.rm = TRUE),
    .groups = "drop"
  )
resumen_caps
## # A tibble: 4 × 9
##   Capital     n   min     q1   med   mean     q3    max    iqr
##   <chr>   <int> <dbl>  <dbl> <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
## 1 Cali       11  2397 21516  54700 53958. 82149  112346 60633 
## 2 Pasto      11   210  1694   4522  4880.  7916   10182  6222 
## 3 Popayán    11   248  1702   4667  6174. 10076.  14958  8374.
## 4 Quibdó     11   163   498.  1071  1380.  2351    2854  1852.
# creo carpeta 
if (!dir.exists("figs")) dir.create("figs")

# guardo la última figura generada
ggsave("figs/boxplot_capitales_F_todos.png", width = 9, height = 6, dpi = 300)
library(dplyr)
library(stringr)
library(ggplot2)
library(scales)

# Serie por capitales (Cali, Popayán, Pasto, Quibdó)
caps_ts <- datos_long %>%
  mutate(Departamento = str_squish(Departamento),
         Muni         = str_squish(Muni)) %>%
  filter(Sexo == "F",
         str_detect(Muni, regex("^cali$|santiago\\s+de\\s+cali|popay[aá]n|^pasto$|quibd[oó]", ignore_case = TRUE))) %>%
  mutate(Capital = case_when(
    str_detect(Muni, regex("^cali$|santiago\\s+de\\s+cali", ignore_case = TRUE)) ~ "Cali",
    str_detect(Muni, regex("popay[aá]n", ignore_case = TRUE)) ~ "Popayán",
    str_detect(Muni, regex("^pasto$",   ignore_case = TRUE)) ~ "Pasto",
    str_detect(Muni, regex("quibd[oó]", ignore_case = TRUE)) ~ "Quibdó",
    TRUE ~ Muni
  )) %>%
  group_by(Capital, Año) %>%
  summarise(Atenciones = sum(Valor, na.rm = TRUE), .groups = "drop")

# Fila del máximo por capital para anotar
max_caps <- caps_ts %>%
  group_by(Capital) %>%
  slice_max(order_by = Atenciones, n = 1, with_ties = FALSE) %>%
  ungroup()

ggplot(caps_ts, aes(Año, Atenciones, color = Capital)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  geom_smooth(se = FALSE, linewidth = .6, linetype = "dashed") +
  geom_label(data = max_caps,
             aes(label = number(Atenciones, big.mark = ".", decimal.mark = ",")),
             vjust = -0.3, label.size = 0.1, fill = "white", alpha = .85,
             show.legend = FALSE) +
  scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
  scale_color_manual(values = c("Cali"="#1b9e77","Pasto"="#d95f02","Popayán"="#7570b3","Quibdó"="#e7298a")) +
  labs(title = "Tendencia de atenciones en capitales de la región (F)",
       subtitle = "Con línea suavizada (LOESS) y valor máximo anotado",
       x = "Año", y = "Atenciones", color = "Capital") +
  theme_minimal(base_size = 12)

library(dplyr)
library(stringr)
library(ggplot2)
library(scales)

valle_rx <- regex("valle(\\s+del\\s+cauca)?", ignore_case = TRUE)
cali_rx  <- regex("^cali$|santiago\\s+de\\s+cali", ignore_case = TRUE)

df_heat <- datos_long %>%
  mutate(Departamento = str_squish(Departamento),
         Muni         = str_squish(Muni)) %>%
  filter(Sexo == "F",
         str_detect(Departamento, valle_rx),
         !str_detect(Muni, cali_rx)) %>%
  group_by(Muni, Año) %>%
  summarise(Atenciones = sum(Valor, na.rm = TRUE), .groups = "drop")

# Ordeno municipios por total acumulado (para que el eje Y sea informativo)
orden_muni <- df_heat %>%
  group_by(Muni) %>% summarise(total = sum(Atenciones), .groups = "drop") %>%
  arrange(desc(total)) %>% pull(Muni)

df_heat$Muni <- factor(df_heat$Muni, levels = orden_muni)

ggplot(df_heat, aes(x = Año, y = Muni, fill = Atenciones)) +
  geom_tile(color = "white", linewidth = .2) +
  scale_fill_viridis_c(option = "C",
                       labels = label_number(big.mark = ".", decimal.mark = ",")) +
  labs(title = "Intensidad de atenciones por municipio — Valle del Cauca (F)",
       subtitle = "Sin Cali. Cada celda corresponde a un año",
       x = "Año", y = "Municipio", fill = "Atenciones") +
  theme_minimal(base_size = 12) +
  theme(panel.grid = element_blank(),
        axis.text.y = element_text(size = 9))

library(ggrepel)

ult <- caps_ts %>% group_by(Capital) %>% slice_max(Año, n = 1)

okabe <- c("Cali"   = "#009E73","Pasto"="#D55E00",
           "Popayán"="#0072B2","Quibdó"="#CC79A7")

ggplot(caps_ts, aes(Año, Atenciones, color = Capital)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  geom_smooth(se = FALSE, linewidth = .6, linetype = "dashed") +
  geom_label_repel(data = ult,
    aes(label = scales::number(Atenciones, big.mark = ".", decimal.mark = ",")),
    seed = 123, size = 3.6, label.size = 0.1, fill = "white", alpha = .9,
    box.padding = .3, min.segment.length = 0, show.legend = FALSE) +
  scale_color_manual(values = okabe) +
  scale_y_continuous(labels = scales::label_number(big.mark = ".", decimal.mark = ","), expand = expansion(mult = c(0.02, .08))) +
  labs(title = "Tendencia de atenciones en capitales de la región (F)",
       subtitle = "Línea suavizada (LOESS) y etiqueta del último año",
       x = "Año", y = "Atenciones", color = "Capital",
       caption = "Fuente: SISPRO-RIPS. Elaboración propia") +
  theme_minimal(base_size = 12) +
  theme(panel.grid.minor = element_blank())

ggplot(df_heat, aes(x = Año, y = Muni, fill = Atenciones)) +
  geom_tile(color = "white", linewidth = .2) +
  scale_x_continuous(breaks = 2009:2019, expand = c(0,0)) +
  scale_fill_viridis_c(option = "C",
    labels = ~ scales::number(.x, accuracy = 1, big.mark = ".", decimal.mark = ","),
    guide = guide_colorbar(barheight = unit(6, "lines"))) +
  labs(title = "Intensidad de atenciones por municipio — Valle del Cauca (F)",
       subtitle = "Sin Cali. Cada celda corresponde a un año",
       x = "Año", y = "Municipio", fill = "Atenciones",
       caption = "Fuente: SISPRO-RIPS. Elaboración propia") +
  theme_minimal(base_size = 12) +
  theme(panel.grid = element_blank(),
        axis.text.y = element_text(size = 9))

if (!dir.exists("figs")) dir.create("figs")
ggsave("figs/viz_capitales_trend.png", width = 9, height = 6, dpi = 300)
ggsave("figs/viz_valle_heatmap.png",  width = 9, height = 6, dpi = 300)
library(dplyr)
library(ggplot2)
library(ggrepel)
library(scales)

# Paleta Okabe–Ito (amigable para daltónicos)
okabe <- c("Cali"="#009E73","Pasto"="#D55E00","Popayán"="#0072B2","Quibdó"="#CC79A7")

# Etiquetas del último año por capital
ult <- caps_ts %>% group_by(Capital) %>% slice_max(Año, n = 1)

p <- ggplot(caps_ts,
            aes(Año, Atenciones, color = Capital)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  # ← Especificamos el método para que NO imprima mensaje
  geom_smooth(method = "loess", formula = y ~ x, se = FALSE,
              linewidth = .6, linetype = "dashed") +
  geom_label_repel(
    data = ult,
    aes(label = number(Atenciones, big.mark = ".", decimal.mark = ",")),
    seed = 123, size = 3.6, label.size = 0.1, fill = "white", alpha = .9,
    box.padding = .3, min.segment.length = 0, show.legend = FALSE
  ) +
  scale_color_manual(values = okabe) +
  scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
  labs(title = "Tendencia de atenciones en capitales de la región (F)",
       subtitle = "Línea suavizada (LOESS) y etiqueta del último año",
       x = "Año", y = "Atenciones", color = "Capital",
       caption = "Fuente: SISPRO-RIPS. Elaboración propia") +
  theme_minimal(base_size = 12) +
  theme(panel.grid.minor = element_blank())

p

# Paquetes
library(dplyr)
library(stringr)
library(ggplot2)
library(ggrepel)
library(scales)

# --- Supongo que ya tengo 'datos_long' con columnas: Muni, Sexo, Año, Valor ---
# Capitales de la región (regex robustas por si cambian tildes o formas)
cali_rx    <- regex("(?:^cali$)|(?:santiago\\s+de\\s+cali)", ignore_case = TRUE)
pasto_rx   <- regex("^pasto$",                  ignore_case = TRUE)
popayan_rx <- regex("popay[aá]n",               ignore_case = TRUE)
quibdo_rx  <- regex("quibd[oó]",                ignore_case = TRUE)

df_cap <- datos_long %>%
  filter(Sexo == "F") %>%
  mutate(
    Capital = case_when(
      str_detect(Muni, cali_rx)    ~ "Cali",
      str_detect(Muni, pasto_rx)   ~ "Pasto",
      str_detect(Muni, popayan_rx) ~ "Popayán",
      str_detect(Muni, quibdo_rx)  ~ "Quibdó",
      TRUE ~ NA_character_
    )
  ) %>%
  filter(!is.na(Capital)) %>%
  group_by(Capital, Año) %>%
  summarise(Atenciones = sum(Valor, na.rm = TRUE), .groups = "drop") %>%
  mutate(Capital = factor(Capital, levels = c("Cali","Pasto","Popayán","Quibdó")))

# Etiquetas con el valor del último año de cada capital
lab_last <- df_cap %>%
  group_by(Capital) %>%
  filter(Año == max(Año)) %>%
  mutate(lbl = label_number(big.mark = ".", decimal.mark = ",")(Atenciones))

# Paleta pastel
pal <- RColorBrewer::brewer.pal(4, "Pastel1")

p <- ggplot(df_cap, aes(x = Año, y = Atenciones, color = Capital)) +
  geom_line(size = 1) +
  geom_point(size = 2) +
  # Línea de tendencia (LOESS) sin banda y punteada
  geom_smooth(se = FALSE, method = "loess", formula = y ~ x,
              linetype = "dashed", size = 0.6, alpha = 0.8) +
  # Etiquetas del último año
  geom_label_repel(
    data = lab_last,
    aes(label = label_number(big.mark = ".", decimal.mark = ",")(Atenciones)),
    nudge_x = 0.25, size = 3, label.size = NA, fill = "white", alpha = 0.95,
    min.segment.length = 0
  ) +
  scale_color_manual(values = pal) +
  scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
  labs(
    title   = "Tendencia de atenciones en capitales de la región (F)",
    # sin subtítulo que mencione LOESS
    x       = "Año",
    y       = "Atenciones",
    color   = "Capital",
    caption = "Fuente: SISPRO-RIPS. Elaboración propia. (Línea punteada = tendencia)"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    legend.position = "right",
    panel.grid.minor = element_blank()
  )

p

# Paquetes
library(dplyr)
library(stringr)
library(ggplot2)
library(ggrepel)
library(scales)
library(plotly)

# Regex de capitales (robustos a tildes/variantes)
cali_rx    <- regex("(?:^cali$)|(?:santiago\\s+de\\s+cali)", ignore_case = TRUE)
pasto_rx   <- regex("^pasto$",                  ignore_case = TRUE)
popayan_rx <- regex("popay[aá]n",               ignore_case = TRUE)
quibdo_rx  <- regex("quibd[oó]",                ignore_case = TRUE)

# Agregación (mismo flujo del gráfico estático)
df_cap <- datos_long %>%
  filter(Sexo == "F") %>%
  mutate(Capital = case_when(
    str_detect(Muni, cali_rx)    ~ "Cali",
    str_detect(Muni, pasto_rx)   ~ "Pasto",
    str_detect(Muni, popayan_rx) ~ "Popayán",
    str_detect(Muni, quibdo_rx)  ~ "Quibdó",
    TRUE ~ NA_character_
  )) %>%
  filter(!is.na(Capital)) %>%
  group_by(Capital, Año) %>%
  summarise(Atenciones = sum(Valor, na.rm = TRUE), .groups = "drop") %>%
  mutate(Capital = factor(Capital, levels = c("Cali","Pasto","Popayán","Quibdó")))

# Texto para tooltip
fmt <- label_number(big.mark = ".", decimal.mark = ",")
df_cap_i <- df_cap %>%
  mutate(tt = paste0(
    "<b>", Capital, "</b><br>",
    "Año: ", Año, "<br>",
    "Atenciones: ", fmt(Atenciones)
  ))

# Colores lindos (pasteles vivos)
pal <- RColorBrewer::brewer.pal(4, "Set2")

# ggplot base (igual al tuyo, pero con 'text' para tooltip)
g_trend <- ggplot(df_cap_i, aes(Año, Atenciones, color = Capital, text = tt)) +
  geom_line(size = 1) +
  geom_point(size = 2) +
  geom_smooth(se = FALSE, method = "loess", formula = y ~ x,
              linetype = "dashed", size = 0.6, alpha = 0.8) +
  scale_color_manual(values = pal) +
  scale_y_continuous(labels = fmt) +
  labs(title = "Tendencia de atenciones en capitales de la región (F)",
       x = "Año", y = "Atenciones", color = "Capital",
       caption = "Fuente: SISPRO-RIPS. Elaboración propia. (Línea punteada = tendencia)") +
  theme_minimal(base_size = 13) +
  theme(panel.grid.minor = element_blank())

# Interactivo
ggplotly(g_trend, tooltip = "text") |>
  layout(hoverlabel = list(bgcolor = "white"),
         legend = list(orientation = "v")) |>
  config(displayModeBar = TRUE, modeBarButtonsToAdd = c("toImage"))
# ---- Heatmap interactivo 2019 (Valle sin Cali, F) ----
suppressPackageStartupMessages({
  library(dplyr); library(stringr); library(plotly)
})

stopifnot("datos_long" %in% ls())

valle_rx <- regex("valle", ignore_case = TRUE)
cali_rx  <- regex("(^cali$|santiago\\s+de\\s+cali)", ignore_case = TRUE)

yr <- 2019

df19 <- datos_long %>%
  filter(Sexo == "F",
         str_detect(Departamento, valle_rx),
         !str_detect(Muni, cali_rx),
         Año == yr) %>%
  group_by(Muni) %>%
  summarise(Atenciones = sum(Valor, na.rm = TRUE), .groups = "drop") %>%
  arrange(desc(Atenciones))

stopifnot(nrow(df19) > 0)

# matriz z (filas=municipios, 1 columna = año)
z <- matrix(df19$Atenciones,
            ncol = 1,
            dimnames = list(df19$Muni, yr))

plot_ly(
  x = c(yr),
  y = df19$Muni,
  z = z,
  type = "heatmap",
  colorscale = "Viridis",                    # <- clave
  colorbar = list(title = "Atenciones"),
  hovertemplate = "<b>%{y}</b><br>Año: %{x}<br>Atenciones: %{z:,}<extra></extra>"
) |>
  layout(
    title = paste0("Intensidad de atenciones — Municipios del Valle (sin Cali), F (", yr, ")"),
    xaxis = list(title = "Año"),
    yaxis = list(title = "Municipio")
  )
# ---- Heatmap interactivo todos los años (Valle sin Cali, F) ----
suppressPackageStartupMessages({
  library(dplyr); library(stringr); library(tidyr); library(plotly)
})

stopifnot("datos_long" %in% ls())

valle_rx <- regex("valle", ignore_case = TRUE)
cali_rx  <- regex("(^cali$|santiago\\s+de\\s+cali)", ignore_case = TRUE)

heat_df <- datos_long %>%
  filter(Sexo == "F",
         str_detect(Departamento, valle_rx),
         !str_detect(Muni, cali_rx)) %>%
  group_by(Muni, Año) %>%
  summarise(Atenciones = sum(Valor, na.rm = TRUE), .groups = "drop")

stopifnot(nrow(heat_df) > 0)

wide <- heat_df %>%
  tidyr::pivot_wider(names_from = Año, values_from = Atenciones, values_fill = 0) %>%
  arrange(Muni)

# ordenar columnas por año numérico (si aplica)
yrs_chr <- names(wide)[-1]
yrs_num <- suppressWarnings(as.numeric(yrs_chr))
if (any(is.na(yrs_num))) {
  x <- yrs_chr
  z <- as.matrix(wide[, -1, drop = FALSE])
} else {
  ord <- order(yrs_num)
  x <- yrs_num[ord]
  z <- as.matrix(wide[, -1, drop = FALSE][, ord, drop = FALSE])
}
y <- wide$Muni

plot_ly(
  x = x, y = y, z = z,
  type = "heatmap",
  colorscale = "Viridis",                    # <- clave
  colorbar = list(title = "Atenciones"),
  hovertemplate = "<b>%{y}</b><br>Año: %{x}<br>Atenciones: %{z:,}<extra></extra>"
) |>
  layout(
    title = "Intensidad de atenciones — Municipios del Valle (sin Cali), F",
    xaxis = list(title = "Año"),
    yaxis = list(title = "Municipio")
  )
# Paquetes
library(dplyr)
library(stringr)
library(ggplot2)
library(ggrepel)
library(scales)
library(plotly)

# Regex robustos (por si cambian tildes o formas)
valle_rx <- regex("valle(\\s+del\\s+cauca)?", ignore_case = TRUE)
cali_rx  <- regex("(?:^cali$)|(?:santiago\\s+de\\s+cali)", ignore_case = TRUE)

cap_df <- datos_long %>%
  filter(Sexo == "F") %>%
  mutate(
    Capital = case_when(
      str_detect(Muni, cali_rx) ~ "Cali",
      str_detect(Muni, regex("^pasto$", ignore_case = TRUE)) ~ "Pasto",
      str_detect(Muni, regex("popay[aá]n", ignore_case = TRUE)) ~ "Popayán",
      str_detect(Muni, regex("quibd[oó]", ignore_case = TRUE)) ~ "Quibdó",
      TRUE ~ NA_character_
    )
  ) %>%
  filter(!is.na(Capital)) %>%
  group_by(Capital, Año) %>%
  summarise(Atenciones = sum(Valor, na.rm = TRUE), .groups = "drop")

# Último año por capital para anotar
ult <- cap_df %>% group_by(Capital) %>% slice_max(Año, n = 1, with_ties = FALSE)

p_line <- ggplot(cap_df, aes(Año, Atenciones, color = Capital)) +
  geom_line(size = 1.2) +
  geom_point(size = 2) +
  geom_smooth(se = FALSE, linetype = 2, size = 0.8) +  # línea de tendencia (loess)
  geom_label_repel(
    data = ult,
    aes(label = label_number(big.mark=".", decimal.mark=",")(Atenciones)),
    size = 3, label.size = 0.2, fill = "white", show.legend = FALSE
  ) +
  scale_color_brewer(palette = "Set2") +   # pasteles agradables
  scale_y_continuous(labels = label_number(big.mark=".", decimal.mark=",")) +
  labs(
    title = "Tendencia de atenciones en capitales de la región (F)",
    subtitle = "Línea punteada: tendencia (LOESS)",
    x = "Año", y = "Atenciones",
    caption = "Fuente: SISPRO-RIPS. Elaboración propia."
  ) +
  theme_minimal(base_size = 13) +
  theme(legend.position = "right")

# Interactivo
p_line_int <- ggplotly(
  p_line,
  tooltip = c("Capital", "Año", "Atenciones")
) %>%
  layout(hoverlabel = list(bgcolor = "white"))

p_line_int
library(plotly)

top10_2019 <- datos_long %>%
  filter(Sexo == "F",
         str_detect(Departamento, valle_rx),
         !str_detect(Muni, cali_rx),
         Año == 2019) %>%
  group_by(Muni) %>%
  summarise(Atenciones = sum(Valor, na.rm = TRUE), .groups = "drop") %>%
  slice_max(Atenciones, n = 10) %>%
  arrange(Atenciones)

plot_ly(
  top10_2019,
  x = ~Atenciones,
  y = ~factor(Muni, levels = top10_2019$Muni),  # ordenado
  type = "bar",
  orientation = "h",
  text = ~paste0(
    "<b>", Muni, "</b><br>",
    "Atenciones: ", scales::label_number(big.mark=".", decimal.mark=",")(Atenciones)
  ),
  hoverinfo = "text",
  marker = list(color = ~Atenciones, colorscale = "Tealgrn")
) %>%
  layout(
    title = "Top-10 municipios del Valle (sin Cali) — 2019, F",
    xaxis = list(title = "Atenciones"),
    yaxis = list(title = "Municipio")
  )
library(dplyr)
library(stringr)
library(plotly)
library(scales)

# Regex que ya vengo usando
valle_rx <- regex("valle(\\s+del\\s+cauca)?", ignore_case = TRUE)
cali_rx  <- regex("(?:^cali$)|(?:santiago\\s+de\\s+cali)", ignore_case = TRUE)

# 1) Agrego 2019, F, Valle y excluimos Cali
treemap_2019 <- datos_long %>%
  filter(Sexo == "F",
         str_detect(Departamento, valle_rx),
         !str_detect(Muni, cali_rx),
         Año == 2019) %>%
  group_by(Muni) %>%
  summarise(Atenciones = as.numeric(sum(Valor, na.rm = TRUE)), .groups = "drop")

# 2) Construyo el árbol con raíz
tree_df <- treemap_2019 %>%
  transmute(label = Muni,
            parent = "Valle del Cauca",
            value = Atenciones) %>%
  bind_rows(tibble(label = "Valle del Cauca",
                   parent = "",
                   value = sum(treemap_2019$Atenciones, na.rm = TRUE)))

# 3) Treemap interactivo (con escala 'Purples' y tooltips claros)
p_tree <- plot_ly(
  data = tree_df,
  type = "treemap",
  labels  = ~label,
  parents = ~parent,
  values  = ~value,
  branchvalues = "total",
  textinfo = "label+value+percent parent",
  hovertemplate = paste0(
    "<b>%{label}</b><br>",
    "Atenciones: %{value:,.0f}<extra></extra>"
  ),
  marker = list(colors = ~value, colorscale = "Purples")
) %>%
  layout(title = "Treemap — Municipios del Valle (sin Cali), 2019 (F)")

p_tree
nrow(treemap_2019)            # debe ser > 0
## [1] 41
str(treemap_2019$Atenciones)  # debe ser numeric
##  num [1:41] 223 831 411 29 0 ...
head(tree_df)
## # A tibble: 6 × 3
##   label        parent          value
##   <chr>        <chr>           <dbl>
## 1 Alcalá       Valle del Cauca   223
## 2 Andalucía    Valle del Cauca   831
## 3 Ansermanuevo Valle del Cauca   411
## 4 Argelia      Valle del Cauca    29
## 5 Bolívar      Valle del Cauca     0
## 6 Buenaventura Valle del Cauca 11702
htmlwidgets::saveWidget(p_tree, "treemap_valle_2019_interactivo.html", selfcontained = TRUE)
library(dplyr); library(ggplot2); library(forcats); library(scales)

df_rank19 <- datos_long %>%
  filter(Sexo=="F",
         str_detect(Departamento, valle_rx),
         !str_detect(Muni, cali_rx),
         Año == 2019) %>%
  group_by(Muni) %>%
  summarise(Atenciones = sum(Valor, na.rm=TRUE), .groups="drop") %>%
  arrange(desc(Atenciones)) %>%
  slice_head(n = 15) %>%
  mutate(Muni = fct_reorder(Muni, Atenciones))

ggplot(df_rank19, aes(Atenciones, Muni, fill = Atenciones)) +
  geom_col(width = .7) +
  geom_text(aes(label = label_number(big.mark=".", decimal.mark=",")(Atenciones)),
            hjust = -0.1, size = 3) +
  scale_fill_viridis_c(option = "plasma") +
  scale_x_continuous(labels = label_number(big.mark=".", decimal.mark=","),
                     expand = expansion(mult = c(0, .1))) +
  labs(title = "Top 15 municipios por atenciones — Valle del Cauca (sin Cali), 2019 (F)",
       x = "Atenciones", y = NULL) +
  theme_minimal(base_size = 12) +
  theme(panel.grid.major.y = element_blank(),
        legend.position = "none")

library(dplyr); library(ggplot2); library(scales)

caps <- c("Cali","Pasto","Popayán","Quibdó")

df_caps <- datos_long %>%
  filter(Sexo=="F", Muni %in% caps) %>%
  group_by(Muni, Año) %>%
  summarise(Atenciones = sum(Valor, na.rm=TRUE), .groups="drop")

ggplot(df_caps, aes(Año, Atenciones, color = Muni)) +
  geom_line(size = 1) +
  geom_point(size = 1.8) +
  scale_color_brewer(palette = "Set2") +
  facet_wrap(~ Muni, scales = "free_y", ncol = 2) +
  scale_y_continuous(labels = label_number(big.mark=".", decimal.mark=",")) +
  labs(title = "Tendencia de atenciones por capital (F) — small multiples",
       x = "Año", y = "Atenciones") +
  theme_minimal(base_size = 12) +
  theme(legend.position = "none")