Introducción

Contexto

La salud de una población no se mide con un solo número. La mortalidad infantil, la esperanza de vida, la fecundidad, la estructura por edades o el gasto en salud describen, cada una, una cara de dos procesos de largo plazo: la transición demográfica, por la cual los países pasan de natalidad y mortalidad altas a niveles bajos y envejecen, y la transición epidemiológica, por la cual las enfermedades transmisibles dejan de ser la principal causa de muerte frente a las no transmisibles. Ambas transiciones siguen un orden: primero cae la mortalidad de los niños, después la natalidad, más tarde la población envejece y, al final, las enfermedades crónicas se vuelven la principal causa de muerte. (Omran, 1971).

El mundo ha avanzado mucho en ese camino, pero de forma muy desigual. Según el Grupo Interinstitucional de las Naciones Unidas para la Estimación de la Mortalidad Infantil, las muertes de menores de 5 años bajaron de 12,5 millones en 1990 a 5,2 millones en 2019, la cifra más baja registrada, y la tasa mundial pasó de 93 a 38 por cada 1.000 nacidos vivos; aun así, más de la mitad de esas muertes ocurrió en África Subsahariana, y 53 países no alcanzarían la meta de los Objetivos de Desarrollo Sostenible para 2030 si seguían con la tendencia de entonces (UN IGME, 2020). En el otro extremo del proceso, las enfermedades no transmisibles causan hoy el 74 % de las muertes del planeta, unos 41 millones al año, y la mayor parte de las muertes prematuras por estas causas ocurre en países de ingreso bajo y medio (OMS, nota descriptiva). La esperanza de vida mundial llegó a 72,8 años en 2019, casi nueve años más que en 1990 (Naciones Unidas, 2022).

Como los países no avanzan al mismo ritmo, hoy conviven perfiles muy distintos: poblaciones jóvenes donde todavía mueren muchos niños por infecciones y desnutrición, sociedades envejecidas cuyo problema es financiar la atención de enfermedades crónicas, y un grupo amplio de países en medio, que enfrentan las dos cargas al mismo tiempo. Colombia pertenece a ese grupo intermedio, y por eso es un caso de interés para este trabajo: en 2019 ya cumplía la meta de mortalidad infantil y tenía una fecundidad por debajo del nivel de reemplazo, pero conservaba rasgos propios de una transición incompleta.

Para comparar a los países en condiciones normales se toma como línea base el año 2019, el último previo a la pandemia de COVID-19, cuyo exceso de mortalidad, estimado en 14,9 millones de muertes entre 2020 y 2021, habría distorsionado la comparación (OMS, 2022). Los datos provienen de los World Development Indicators del Banco Mundial (Banco Mundial, 2026).

Planteamiento del problema

Los organismos internacionales suelen agrupar a los países por nivel de ingreso o por región para asignar cooperación, fijar prioridades y comparar resultados. Sin embargo, ninguna de las dos clasificaciones se construye con información de salud: un país puede ser de ingreso medio-alto y tener un perfil sanitario parecido al de un país pobre, o al revés. Si se quiere saber en qué etapa sanitaria y demográfica está cada país, hace falta una agrupación construida a partir de los propios indicadores de salud.

Construirla no es inmediato. Los 15 indicadores disponibles para 162 países plantean dos dificultades. La primera es la alta dimensionalidad y la colinealidad: 41 de los 105 pares de variables tienen una correlación superior a 0,8 en valor absoluto (la mortalidad infantil y la de menores de 5 años, por ejemplo, miden fenómenos casi idénticos), por lo que analizarlas una a una es redundante y no revela cómo se relacionan entre sí. La segunda es la ausencia de una tipología: no es evidente qué países comparten un mismo perfil sanitario y demográfico, qué indicadores los separan, ni si esos grupos coinciden con el nivel de ingreso o la región.

Además, no existe una variable respuesta ni una clasificación previa que predecir. Por eso el problema se aborda con aprendizaje no supervisado: el Análisis de Componentes Principales (ACP) resume los indicadores en pocas dimensiones interpretables y la clusterización jerárquica de Ward agrupa a los países a partir de ellas. Desde la ingeniería industrial, el ejercicio es análogo a una segmentación de clientes o de proveedores: no se trata de predecir, sino de encontrar grupos homogéneos que permitan tomar decisiones distintas para cada uno, en este caso decisiones de política sanitaria.

Pregunta de investigación

¿En qué medida los indicadores de mortalidad, salud y estructura demográfica permiten identificar y caracterizar grupos de países con perfiles similares, y cómo se pueden agrupar los países según esos patrones mediante el Análisis de Componentes Principales y la clusterización jerárquica de Ward?

De esta pregunta se derivan tres preguntas específicas:

  1. ¿Qué dimensiones latentes resumen los 15 indicadores y qué proporción de la variabilidad entre países explican?
  2. ¿Cuántos grupos de países se distinguen y qué rasgos definen a cada uno?
  3. ¿Los grupos coinciden con el nivel de ingreso y la región, o revelan perfiles que esas clasificaciones no capturan?

Objetivos

Objetivo general. Segmentar a los países según sus perfiles de mortalidad, salud y estructura demográfica en 2019, combinando ACP y clusterización jerárquica de Ward.

Objetivos específicos.

  • Describir el comportamiento de las 15 variables cuantitativas y de las tres variables categóricas de apoyo.
  • Reducir la dimensionalidad con ACP e interpretar y nombrar los componentes retenidos.
  • Agrupar los países con el método de Ward sobre los componentes estandarizados y determinar el número adecuado de grupos.
  • Caracterizar y nombrar los grupos, y contrastarlos con el nivel de ingreso y la región.
  • Identificar posibles usos del análisis en economía y políticas públicas.

Hipótesis de trabajo

A partir de la teoría de las transiciones se plantean tres hipótesis, que se contrastan en las conclusiones:

  • H1. Los indicadores no son independientes: un primer componente concentrará la mayor parte de la variabilidad y ordenará a los países según su avance en la transición demográfica y epidemiológica.
  • H2. Los países no formarán bloques aislados sino cortes de un gradiente continuo, de modo que los grupos representarán etapas de un mismo proceso.
  • H3. Los grupos se parecerán al nivel de ingreso, pero sin coincidir del todo con él: habrá países cuyo perfil de salud sea mejor o peor de lo que su ingreso haría esperar.

Metodología

Tema, año y fuente de los datos

Elección del tema

La mortalidad es uno de los indicadores que mejor resume el nivel de desarrollo de un país, porque refleja en pocas cifras el acceso a servicios de salud, la nutrición, el saneamiento y las condiciones de vida de la población. Sin embargo, no se comporta de forma aislada: se relaciona con la fecundidad, con la estructura por edades y con el tipo de enfermedades que causan las muertes. Estos procesos conjuntos describen la transición demográfica y la transición epidemiológica, es decir, el paso de sociedades con mortalidad y natalidad altas, dominadas por enfermedades infecciosas, a sociedades con mortalidad y natalidad bajas, más envejecidas y dominadas por enfermedades no transmisibles.

Por esta razón el trabajo no se limita a comparar tasas de mortalidad, sino que construye un perfil multidimensional de salud y demografía para cada país. Al tratarse de muchos indicadores correlacionados entre sí, el ACP permite resumirlos en pocas dimensiones interpretables, y la clusterización jerárquica de Ward permite agrupar países con perfiles semejantes sin imponer categorías externas como el ingreso o la región.

Elección del año 2019

Se trabaja con el año 2019 por tres razones:

  1. Es el último año previo a la pandemia de COVID-19. La OMS estimó cerca de 14,9 millones de muertes en exceso asociadas a la pandemia entre enero de 2020 y diciembre de 2021, y la esperanza de vida mundial retrocedió de 72,8 años en 2019 a 71,0 en 2021. Usar 2020 o 2021 mezclaría la estructura habitual de la mortalidad de cada país con un choque que además se registró de forma muy desigual.
  2. Refleja la estructura de largo plazo de los países. Los indicadores de 2019 describen diferencias estructurales entre sistemas de salud y etapas de la transición demográfica, que es lo que se quiere segmentar.
  3. Tiene buena cobertura de información. Las series de causas de muerte provienen de estimaciones de la OMS que no se publican para todos los años, y 2019 cuenta con cobertura amplia, lo que permite conservar una muestra grande tras eliminar los países con datos faltantes.

Fuente de los datos

Los datos provienen de los World Development Indicators (WDI) del Banco Mundial, descargados desde DataBank, que reúne estadísticas nacionales y estimaciones de organismos internacionales en una base comparable (Banco Mundial, 2026). Se trabaja únicamente con países: se excluyen los agregados regionales y de ingreso (por ejemplo “World” o “Latin America & Caribbean”), porque duplicarían información ya contenida en los países que los componen y distorsionarían las distancias entre observaciones. En la misma descarga se incluyó el ingreso nacional bruto per cápita (método Atlas), que no entra al modelo pero sirve para asignar el nivel de ingreso de cada país. La región corresponde a las siete regiones del Banco Mundial, asignadas a partir del código de cada país con el paquete countrycode, que también se usó para traducir al español los nombres de los países.

Selección y descripción de las variables

Criterios de selección

Se seleccionaron 15 variables cuantitativas con cuatro criterios:

  • Pertinencia conceptual: cada variable describe mortalidad, perfil epidemiológico, longevidad, estructura demográfica o capacidad del sistema de salud, las dimensiones de las transiciones demográfica y epidemiológica.
  • Comparabilidad: todas son tasas, porcentajes o años, y no conteos absolutos, de modo que el tamaño de la población no domine la comparación (por eso no se incluye la población total).
  • Cobertura: se priorizaron indicadores con datos para la gran mayoría de países en 2019. Se descartó el número de médicos por 1.000 habitantes, que solo tiene dato para cerca de la mitad de las economías y reducía de forma notable la muestra completa.
  • Ausencia de redundancia exacta: las tres causas de muerte (transmisibles, no transmisibles y lesiones) suman 100 %, por lo que incluir las tres produciría una dependencia lineal perfecta. Se conservaron las dos primeras.

Descripción por dimensión

Mortalidad y longevidad. Reúne los indicadores que miden cuánto y a qué edades se muere en cada país. La mortalidad de menores de 5 años y la mortalidad infantil (probabilidad de morir antes de los cinco años y del primer año, por 1.000 nacidos vivos) son los indicadores clásicos de desarrollo sanitario, pues dependen de la atención materno-infantil, la nutrición y el saneamiento. La mortalidad adulta masculina y la femenina (probabilidad de morir entre los 15 y los 60 años, por 1.000 adultos) recogen enfermedades crónicas, violencia y accidentes, y se incluyen por separado porque los patrones por sexo difieren. La tasa bruta de mortalidad (muertes por 1.000 habitantes) resume la mortalidad general, pero depende de la estructura por edades: un país envejecido puede tener una tasa alta aun con buena salud, por lo que aporta información sobre un fenómeno distinto al de las demás. Por último, la esperanza de vida al nacer sintetiza en una sola cifra, en años, todos los riesgos de muerte.

Perfil epidemiológico. Mide qué tipo de enfermedades causan las muertes. Las muertes por enfermedades transmisibles, maternas, perinatales y nutricionales señalan una carga todavía dominada por causas en buena parte prevenibles, mientras que las muertes por enfermedades no transmisibles (cáncer, enfermedades cardiovasculares, diabetes) indican una etapa avanzada de la transición epidemiológica. Ambas son proporciones del mismo total de muertes, por lo que se mueven en sentido contrario, y por esa razón no se incluye la tercera categoría (lesiones).

Estructura demográfica. Describe cómo se renueva y cómo se compone por edades la población. La tasa bruta de natalidad (nacimientos por 1.000 habitantes) y la tasa de fecundidad (hijos por mujer) captan el lado de la natalidad en la transición demográfica; la segunda es independiente de la estructura por edades. La población de 0 a 14 años mide el peso de la población joven, con alta demanda de servicios materno-infantiles y educativos, y la población de 65 años o más mide el envejecimiento, que eleva la demanda de atención de enfermedades crónicas.

Sistema de salud y determinantes. Aproxima los recursos y las condiciones que sostienen la salud. El gasto corriente en salud (% del PIB) refleja el esfuerzo económico del país; la prevalencia de desnutrición (% de la población) es un determinante básico de la salud, aunque en los países con prevalencia inferior a 2,5 % el Banco Mundial la reporta truncada en ese valor; y la vacunación DPT (% de niños de 12 a 23 meses) aproxima la cobertura y el alcance de la atención primaria.

Seis de las quince variables pertenecen al bloque de mortalidad y longevidad, por lo que es esperable que el primer componente refleje con fuerza ese conjunto. Esto es coherente con el objetivo del trabajo y se discute como limitación en las conclusiones.

definiciones <- c(
  Mort_Menores5     = "Probabilidad de morir antes de los 5 años (por 1.000 nacidos vivos)",
  Mort_Infantil     = "Probabilidad de morir antes del primer año (por 1.000 nacidos vivos)",
  Tasa_Mortalidad   = "Muertes por cada 1.000 habitantes a mitad de año",
  Mort_Adulta_Masc  = "Probabilidad de que un hombre de 15 años muera antes de los 60 (por 1.000)",
  Mort_Adulta_Fem   = "Probabilidad de que una mujer de 15 años muera antes de los 60 (por 1.000)",
  Esperanza_Vida    = "Años que viviría en promedio un recién nacido con la mortalidad actual",
  Muerte_Transmis   = "Muertes por enfermedades transmisibles, maternas, perinatales y nutricionales (% del total)",
  Muerte_NoTransmis = "Muertes por enfermedades no transmisibles (% del total)",
  Tasa_Natalidad    = "Nacimientos por cada 1.000 habitantes a mitad de año",
  Fecundidad        = "Número promedio de hijos por mujer con las tasas por edad actuales",
  Pob_0a14          = "Población de 0 a 14 años (% de la población total)",
  Pob_65mas         = "Población de 65 años o más (% de la población total)",
  Gasto_Salud       = "Gasto corriente en salud, público y privado (% del PIB)",
  Desnutricion      = "Población con consumo de energía alimentaria insuficiente (%)",
  Vacunacion_DPT    = "Niños de 12 a 23 meses vacunados con DPT (%)"
)

orden_vars <- unlist(dimensiones)

tab_vars <- tibble(
  Dimension = dim_tab$Dimension[match(orden_vars, dim_tab$var)],
  Variable = unname(etiquetas[orden_vars]),
  Codigo = unname(vars[orden_vars]),
  Definicion = unname(definiciones[orden_vars])
)

tabla_t(
  "Variables cuantitativas del análisis, agrupadas por dimensión",
  kbl(tab_vars, format = "html", align = "l",
      col.names = c("Dimensión", "Variable", "Código WDI", "Definición y unidad")) %>%
    kable_styling(full_width = TRUE) %>%
    column_spec(1, color = "#0b522c") %>%
    collapse_rows(columns = 1, valign = "middle")
)
Tabla 1. Variables cuantitativas del análisis, agrupadas por dimensión
Dimensión Variable Código WDI Definición y unidad
Mortalidad y longevidad Mortalidad de menores de 5 años SH.DYN.MORT Probabilidad de morir antes de los 5 años (por 1.000 nacidos vivos)
Mortalidad infantil SP.DYN.IMRT.IN Probabilidad de morir antes del primer año (por 1.000 nacidos vivos)
Tasa bruta de mortalidad SP.DYN.CDRT.IN Muertes por cada 1.000 habitantes a mitad de año
Mortalidad adulta masculina SP.DYN.AMRT.MA Probabilidad de que un hombre de 15 años muera antes de los 60 (por 1.000)
Mortalidad adulta femenina SP.DYN.AMRT.FE Probabilidad de que una mujer de 15 años muera antes de los 60 (por 1.000)
Esperanza de vida al nacer SP.DYN.LE00.IN Años que viviría en promedio un recién nacido con la mortalidad actual
Perfil epidemiológico Muertes por enfermedades transmisibles SH.DTH.COMM.ZS Muertes por enfermedades transmisibles, maternas, perinatales y nutricionales (% del total)
Muertes por enfermedades no transmisibles SH.DTH.NCOM.ZS Muertes por enfermedades no transmisibles (% del total)
Estructura demográfica Tasa bruta de natalidad SP.DYN.CBRT.IN Nacimientos por cada 1.000 habitantes a mitad de año
Tasa de fecundidad SP.DYN.TFRT.IN Número promedio de hijos por mujer con las tasas por edad actuales
Población de 0 a 14 años SP.POP.0014.TO.ZS Población de 0 a 14 años (% de la población total)
Población de 65 años o más SP.POP.65UP.TO.ZS Población de 65 años o más (% de la población total)
Sistema de salud y determinantes Gasto corriente en salud SH.XPD.CHEX.GD.ZS Gasto corriente en salud, público y privado (% del PIB)
Prevalencia de desnutrición SN.ITK.DEFC.ZS Población con consumo de energía alimentaria insuficiente (%)
Vacunación DPT SH.IMM.IDPT Niños de 12 a 23 meses vacunados con DPT (%)
Fuente: elaboración propia con base en los WDI, 2019.

La tabla resume el diseño del análisis: cuatro dimensiones y quince indicadores, cada uno con su código del Banco Mundial para que cualquier lector pueda ubicarlo en DataBank. El bloque de mortalidad y longevidad es el más numeroso (seis variables) y el perfil epidemiológico el más pequeño (dos), de modo que el peso de cada dimensión no es uniforme, algo que se retoma al interpretar los componentes.

wpp <- "División de Población de las Naciones Unidas (World Population Prospects)"
igme <- "Grupo Interinstitucional de las Naciones Unidas para la Estimación de la Mortalidad Infantil (UNICEF, OMS, Banco Mundial y ONU)"
ghe <- "Organización Mundial de la Salud (Estimaciones Mundiales de Salud)"

origen_var <- tribble(
  ~codigo,               ~organismo,                                                              ~obtencion,
  "SH.DYN.MORT",         igme,                                                                    "Estimación modelada con registros vitales, censos y encuestas de hogares",
  "SP.DYN.IMRT.IN",      igme,                                                                    "Estimación modelada con registros vitales, censos y encuestas de hogares",
  "SP.DYN.CDRT.IN",      wpp,                                                                     "Estimación demográfica a partir de censos, encuestas y registros",
  "SP.DYN.AMRT.MA",      wpp,                                                                     "Se calcula con tablas de vida construidas por edad",
  "SP.DYN.AMRT.FE",      wpp,                                                                     "Se calcula con tablas de vida construidas por edad",
  "SP.DYN.LE00.IN",      wpp,                                                                     "Se calcula con tablas de vida construidas por edad",
  "SH.DTH.COMM.ZS",      ghe,                                                                     "Estimación modelada; se publica solo para algunos años",
  "SH.DTH.NCOM.ZS",      ghe,                                                                     "Estimación modelada; se publica solo para algunos años",
  "SP.DYN.CBRT.IN",      wpp,                                                                     "Estimación demográfica a partir de censos, encuestas y registros",
  "SP.DYN.TFRT.IN",      wpp,                                                                     "Estimación demográfica a partir de censos, encuestas y registros",
  "SP.POP.0014.TO.ZS",   wpp,                                                                     "Proyección de la población por edades",
  "SP.POP.65UP.TO.ZS",   wpp,                                                                     "Proyección de la población por edades",
  "SH.XPD.CHEX.GD.ZS",   "Organización Mundial de la Salud (Base de Datos Mundial de Gasto en Salud)", "Cuentas nacionales de salud reportadas por cada país",
  "SN.ITK.DEFC.ZS",      "Organización de las Naciones Unidas para la Alimentación y la Agricultura (FAO)", "Estimación con balances de alimentos y encuestas; los valores menores de 2,5 % se reportan como 2,5",
  "SH.IMM.IDPT",         "OMS y UNICEF (estimaciones nacionales de cobertura de vacunación)",       "Registros administrativos y encuestas de cobertura",
  "NY.GNP.PCAP.CD",      "Banco Mundial (cuentas nacionales, método Atlas)",                        "Se usa solo para asignar el nivel de ingreso; no entra al modelo"
)

periodo <- if (!is.null(meta_series) && "reference_period" %in% names(meta_series)) {
  meta_series$reference_period[match(origen_var$codigo, meta_series$code)]
} else NA_character_

ficha <- origen_var %>%
  mutate(clave = names(vars)[match(codigo, vars)],
         Variable = ifelse(codigo == cod_inb, "INB per cápita (método Atlas)", unname(etiquetas[clave])),
         Unidad = ifelse(codigo == cod_inb, "dólares corrientes por habitante", unname(unidades[clave])),
         Periodo = coalesce(periodo, "No disponible")) %>%
  arrange(match(codigo, c(unname(vars[orden_vars]), cod_inb))) %>%
  select(Código = codigo, Variable, Unidad, `Quién produce el dato` = organismo,
         `Cómo se obtiene` = obtencion, `Años disponibles` = Periodo)

tabla_t("Origen de cada indicador: quién lo produce y cómo se obtiene",
        kbl(ficha, format = "html", align = "l") %>%
          kable_styling(full_width = TRUE) %>%
          column_spec(1, color = "#0b522c"),
        fuente = "Fuente: elaboración propia con base en los metadatos de los World Development Indicators.")
Tabla 2. Origen de cada indicador: quién lo produce y cómo se obtiene
Código Variable Unidad Quién produce el dato Cómo se obtiene Años disponibles
SH.DYN.MORT Mortalidad de menores de 5 años muertes por 1.000 nacidos vivos Grupo Interinstitucional de las Naciones Unidas para la Estimación de la Mortalidad Infantil (UNICEF, OMS, Banco Mundial y ONU) Estimación modelada con registros vitales, censos y encuestas de hogares 1960-2024
SP.DYN.IMRT.IN Mortalidad infantil muertes por 1.000 nacidos vivos Grupo Interinstitucional de las Naciones Unidas para la Estimación de la Mortalidad Infantil (UNICEF, OMS, Banco Mundial y ONU) Estimación modelada con registros vitales, censos y encuestas de hogares 1960-2024
SP.DYN.CDRT.IN Tasa bruta de mortalidad muertes por 1.000 habitantes División de Población de las Naciones Unidas (World Population Prospects) Estimación demográfica a partir de censos, encuestas y registros 1960-2024
SP.DYN.AMRT.MA Mortalidad adulta masculina por 1.000 hombres adultos División de Población de las Naciones Unidas (World Population Prospects) Se calcula con tablas de vida construidas por edad 1960-2024
SP.DYN.AMRT.FE Mortalidad adulta femenina por 1.000 mujeres adultas División de Población de las Naciones Unidas (World Population Prospects) Se calcula con tablas de vida construidas por edad 1960-2024
SP.DYN.LE00.IN Esperanza de vida al nacer años División de Población de las Naciones Unidas (World Population Prospects) Se calcula con tablas de vida construidas por edad 1960-2024
SH.DTH.COMM.ZS Muertes por enfermedades transmisibles % del total de muertes Organización Mundial de la Salud (Estimaciones Mundiales de Salud) Estimación modelada; se publica solo para algunos años 2000-2021
SH.DTH.NCOM.ZS Muertes por enfermedades no transmisibles % del total de muertes Organización Mundial de la Salud (Estimaciones Mundiales de Salud) Estimación modelada; se publica solo para algunos años 2000-2021
SP.DYN.CBRT.IN Tasa bruta de natalidad nacimientos por 1.000 habitantes División de Población de las Naciones Unidas (World Population Prospects) Estimación demográfica a partir de censos, encuestas y registros 1960-2024
SP.DYN.TFRT.IN Tasa de fecundidad hijos por mujer División de Población de las Naciones Unidas (World Population Prospects) Estimación demográfica a partir de censos, encuestas y registros 1960-2024
SP.POP.0014.TO.ZS Población de 0 a 14 años % de la población total División de Población de las Naciones Unidas (World Population Prospects) Proyección de la población por edades 1960-2025
SP.POP.65UP.TO.ZS Población de 65 años o más % de la población total División de Población de las Naciones Unidas (World Population Prospects) Proyección de la población por edades 1960-2025
SH.XPD.CHEX.GD.ZS Gasto corriente en salud % del PIB Organización Mundial de la Salud (Base de Datos Mundial de Gasto en Salud) Cuentas nacionales de salud reportadas por cada país 2000-2024
SN.ITK.DEFC.ZS Prevalencia de desnutrición % de la población Organización de las Naciones Unidas para la Alimentación y la Agricultura (FAO) Estimación con balances de alimentos y encuestas; los valores menores de 2,5 % se reportan como 2,5 2001-2024
SH.IMM.IDPT Vacunación DPT % de niños de 12 a 23 meses OMS y UNICEF (estimaciones nacionales de cobertura de vacunación) Registros administrativos y encuestas de cobertura 1980-2024
NY.GNP.PCAP.CD INB per cápita (método Atlas) dólares corrientes por habitante Banco Mundial (cuentas nacionales, método Atlas) Se usa solo para asignar el nivel de ingreso; no entra al modelo 1962-2025
Fuente: elaboración propia con base en los metadatos de los World Development Indicators.

Esta segunda tabla responde una pregunta que suele pasarse por alto: de dónde sale cada número. El Banco Mundial no mide estos indicadores directamente; los reúne de organismos especializados. Las mortalidades de la niñez vienen de un grupo de Naciones Unidas que combina registros, censos y encuestas; las causas de muerte, de modelos de la OMS; y casi todas las variables demográficas, de las proyecciones de población de Naciones Unidas. Esto importa para leer los resultados: en países con registros débiles, varios valores son estimaciones modeladas y no conteos reales, de modo que dos países con cifras muy parecidas pueden estar igual de bien o igual de mal medidos. La columna de años disponibles muestra, además, por qué 2019 es un buen año: todas las series lo cubren.

Datos y depuración

La descarga se realizó desde DataBank para todas las entidades y el año 2019, con las 15 variables del modelo, el INB per cápita (para el nivel de ingreso) y el indicador de médicos, que se descartó después. El procesamiento siguió cinco pasos: lectura del archivo y separación de los datos, las notas al pie y la ficha oficial de los indicadores; conversión a formato ancho, con una fila por país y una columna por variable; asignación de la región a partir del código de cada país, lo que además retira los agregados regionales y de ingreso, que no tienen región; clasificación del ingreso con los umbrales del Banco Mundial; y eliminación de los países con algún dato faltante en las 15 variables, requisito del ACP y de la clusterización jerárquica.

archivo_datos <- c("MetadataWDB.csv", "DataWDB.csv", "datos_mortalidad.csv")
archivo_datos <- archivo_datos[file.exists(archivo_datos)][1]
if (is.na(archivo_datos)) {
  stop("No se encontró la descarga de DataBank (MetadataWDB.csv o DataWDB.csv) en la carpeta del .Rmd.")
}

vars <- c(
  Mort_Menores5     = "SH.DYN.MORT",
  Tasa_Mortalidad   = "SP.DYN.CDRT.IN",
  Mort_Infantil     = "SP.DYN.IMRT.IN",
  Mort_Adulta_Masc  = "SP.DYN.AMRT.MA",
  Mort_Adulta_Fem   = "SP.DYN.AMRT.FE",
  Muerte_Transmis   = "SH.DTH.COMM.ZS",
  Muerte_NoTransmis = "SH.DTH.NCOM.ZS",
  Esperanza_Vida    = "SP.DYN.LE00.IN",
  Tasa_Natalidad    = "SP.DYN.CBRT.IN",
  Fecundidad        = "SP.DYN.TFRT.IN",
  Pob_65mas         = "SP.POP.65UP.TO.ZS",
  Pob_0a14          = "SP.POP.0014.TO.ZS",
  Gasto_Salud       = "SH.XPD.CHEX.GD.ZS",
  Desnutricion      = "SN.ITK.DEFC.ZS",
  Vacunacion_DPT    = "SH.IMM.IDPT"
)
cod_inb <- "NY.GNP.PCAP.CD"

leer_databank <- function(ruta) {
  lin <- readLines(ruta, warn = FALSE)
  lin[1] <- sub("^\xef\xbb\xbf", "", lin[1], useBytes = TRUE)
  if (!all(validUTF8(lin))) lin <- iconv(lin, "WINDOWS-1252", "UTF-8", sub = "")
  fin <- which(lin == "" | grepl("^,+$", lin) | grepl("^Data from database", lin))[1]
  if (is.na(fin)) fin <- length(lin) + 1
  datos <- read_csv(I(paste(lin[1:(fin - 1)], collapse = "\n")), na = c("..", ""),
                    show_col_types = FALSE)
  ini <- grep("^Code,", lin)[1]
  meta <- if (is.na(ini)) NULL else
    read_csv(I(paste(lin[ini:length(lin)], collapse = "\n")), show_col_types = FALSE)
  list(datos = datos, meta = meta)
}

db <- leer_databank(archivo_datos)

crudo <- db$datos %>%
  clean_names() %>%
  filter(!is.na(country_code), country_code != "")
col_anio <- grep("yr\\d{4}", names(crudo), value = TRUE)[1]

ancho <- crudo %>%
  select(country_name, country_code, series_code, valor = all_of(col_anio)) %>%
  mutate(valor = suppressWarnings(as.numeric(valor))) %>%
  pivot_wider(names_from = series_code, values_from = valor)

if (!cod_inb %in% names(ancho)) {
  stop("La descarga no trae el indicador NY.GNP.PCAP.CD (INB per cápita), necesario para el nivel de ingreso.")
}
ancho$INB_pc <- ancho[[cod_inb]]
ancho <- ancho %>% select(country_name, country_code, all_of(vars), INB_pc)

meta_series <- if (is.null(db$meta)) NULL else
  db$meta %>% clean_names() %>% filter(code %in% c(vars, cod_inb))

ancho$country_name <- coalesce(
  countrycode(ancho$country_code, "iso3c", "cldr.name.es", warn = FALSE),
  ancho$country_name)

traducir_region <- function(x) case_when(
  str_detect(x, "East Asia") ~ "Asia Oriental y Pacífico",
  str_detect(x, "Europe") ~ "Europa y Asia Central",
  str_detect(x, "Latin") ~ "América Latina y el Caribe",
  str_detect(x, "Middle East") ~ "Oriente Medio y Norte de África",
  str_detect(x, "North America") ~ "Norteamérica",
  str_detect(x, "South Asia") ~ "Asia Meridional",
  str_detect(x, "Sub-Saharan") ~ "África Subsahariana",
  TRUE ~ x
)

niveles_ing <- c("Bajo", "Medio-bajo", "Medio-alto", "Alto", "Sin clasificar")
umbrales_inb <- c(1035, 4045, 12535)
clasificar_inb <- function(x) as.character(cut(x, c(-Inf, umbrales_inb, Inf),
                                               labels = niveles_ing[1:4], right = TRUE))

ancho$region_en <- countrycode(ancho$country_code, "iso3c", "region", warn = FALSE,
                               custom_match = c(XKX = "Europe & Central Asia"))
ancho$income <- factor(coalesce(clasificar_inb(ancho$INB_pc), "Sin clasificar"), levels = niveles_ing)

paises_all <- ancho %>%
  filter(!is.na(region_en)) %>%
  mutate(region = traducir_region(region_en))
paises <- drop_na(paises_all, all_of(names(vars)))

n_sin_inb <- sum(is.na(paises$INB_pc))

fuente_ingreso <- paste0(
  "se construyó con el ingreso nacional bruto (INB) per cápita de 2019 por el método Atlas (código ", cod_inb,
  "), que viene en la misma descarga de DataBank, y los umbrales con los que el Banco Mundial clasificó a los países según su ingreso de ese año (año fiscal 2021): hasta US$ 1.035, ingreso bajo; de US$ 1.036 a 4.045, medio-bajo; de US$ 4.046 a 12.535, medio-alto; y más de US$ 12.535, alto (Banco Mundial, 2020)",
  if (n_sin_inb > 0) paste0(". ", n_sin_inb, if (n_sin_inb == 1) " país sin dato de INB quedó" else " países sin dato de INB quedaron",
                            " en la categoría «Sin clasificar»") else "")

El archivo descargado contiene 266 entidades. Tras retirar los agregados quedan 216 países y economías individuales, y 162 de ellos tienen información completa en las 15 variables; esos 162 países son la muestra de todo el análisis. Como referencia de la cobertura de 2019, 185 de las 216 economías cuentan con estimación de causas de muerte.

faltantes <- paises_all %>%
  summarise(across(all_of(names(vars)), ~ sum(is.na(.x)))) %>%
  pivot_longer(everything(), names_to = "var", values_to = "Países sin dato") %>%
  mutate(Variable = unname(etiquetas[var]),
         `% de las economías` = 100 * `Países sin dato` / nrow(paises_all)) %>%
  arrange(desc(`Países sin dato`)) %>%
  select(Variable, `Países sin dato`, `% de las economías`)

tabla_t(
  "Países sin dato por variable antes de eliminar los casos incompletos",
  dt(faltantes, n = 8) %>% fr("% de las economías", 1)
)
Tabla 3. Países sin dato por variable antes de eliminar los casos incompletos
Fuente: elaboración propia con base en los WDI, 2019.

La variable que más restringe la muestra es la prevalencia de desnutrición, con 50 economías sin dato, seguida de las muertes por enfermedades transmisibles (31). El resto de las variables tiene una cobertura casi completa, por lo que la muestra final depende sobre todo de esas dos series.

excl <- paises_all %>%
  filter(if_any(all_of(names(vars)), is.na)) %>%
  pull(country_name) %>%
  sort()

cat("<details><summary><b>Ver los ", length(excl), " países excluidos por datos incompletos</b></summary><p>",
    paste(excl, collapse = ", "), ".</p></details>", sep = "")
Ver los 54 países excluidos por datos incompletos

Andorra, Antigua y Barbuda, Aruba, Bahamas, Baréin, Bermudas, Bielorrusia, Brunéi, Burundi, Bután, Catar, Corea del Norte, Curazao, Dominica, Eritrea, Eslovaquia, Gibraltar, Granada, Groenlandia, Guam, Guinea Ecuatorial, Isla de Man, Islas Caimán, Islas Feroe, Islas Marianas del Norte, Islas Marshall, Islas Turcas y Caicos, Islas Vírgenes Británicas, Islas Vírgenes de EE. UU., Kosovo, Lesoto, Liechtenstein, Maldivas, Micronesia, Fed. Sts., Mónaco, Nauru, Nueva Caledonia, Palaos, Polinesia Francesa, Puerto Rico, RAE de Hong Kong (China), RAE de Macao (China), Samoa Americana, San Cristóbal y Nieves, San Marino, Santa Lucía, Singapur, Sint Maarten, St. Martin (French part), Sudán del Sur, Territorios Palestinos, Tonga, Tuvalu, Yemen.

Los países excluidos son, en su mayoría, territorios dependientes, microestados y economías insulares pequeñas, junto con algunos Estados con sistemas estadísticos frágiles. Por eso las conclusiones se refieren a los países con información completa y no necesariamente a todo el mundo.

Variables categóricas de apoyo

El taller no exige variables categóricas, pero tres de ellas aportan algo que las 15 cuantitativas no pueden: una referencia externa contra la cual leer los grupos. No participan en el ACP ni en la clusterización; se usan para describir los datos y para comprobar si los grupos encontrados coinciden con clasificaciones conocidas.

  • Nivel de ingreso. DataBank no tiene una serie con el grupo de ingreso, porque es un atributo de cada país y no un indicador. Por eso se construyó con el ingreso nacional bruto (INB) per cápita de 2019 por el método Atlas (código NY.GNP.PCAP.CD), que viene en la misma descarga de DataBank, y los umbrales con los que el Banco Mundial clasificó a los países según su ingreso de ese año (año fiscal 2021): hasta US$ 1.035, ingreso bajo; de US$ 1.036 a 4.045, medio-bajo; de US$ 4.046 a 12.535, medio-alto; y más de US$ 12.535, alto (Banco Mundial, 2020).
  • Región. Tampoco es una serie de DataBank. Se usaron las siete regiones del Banco Mundial, asignadas a partir del código de cada país con el paquete countrycode.
  • Meta ODS 3.2 de mortalidad de menores de 5 años. No la publica el Banco Mundial: se construye con la variable SH.DYN.MORT. Clasifica a cada país según el Objetivo de Desarrollo Sostenible 3.2, que fija como referencia una mortalidad de menores de 5 años de 25 por 1.000 nacidos vivos o menos (Naciones Unidas, 2015). La categoría “Cumple” agrupa a los países que ya están en o por debajo de ese umbral. A diferencia de las otras dos, se deriva de una variable del modelo, por lo que no es una validación independiente: sirve para traducir los grupos al lenguaje de las políticas públicas y ver cuáles están lejos de la meta.

Región e ingreso no se construyen con ninguno de los 15 indicadores, por lo que sirven como validación independiente: si grupos formados solo con salud y demografía se parecen a ellas, la segmentación tiene sentido más allá de los datos con que se hizo.

Se evaluaron otras dos categorías, el nivel de gasto en salud (terciles) y el perfil epidemiológico (corte en la mediana de muertes no transmisibles), y se descartaron: ambas se construyen con variables que ya están en el modelo, exigen cortes arbitrarios y no aportan una referencia externa, de modo que habrían duplicado información sin ayudar a validar nada.

paises <- paises %>%
  mutate(
    income = droplevels(income),
    Meta_ODS = factor(if_else(Mort_Menores5 <= 25, "Cumple", "No cumple"),
                      levels = c("Cumple", "No cumple"))
  )
tab_cat <- tibble(
  Variable = c("Región", "Nivel de ingreso", "Meta ODS 3.2 (menores de 5 años)"),
  Categorias = c("Siete regiones del Banco Mundial",
                 "Bajo, medio-bajo, medio-alto y alto (más sin clasificar)",
                 "Cumple (25 por 1.000 o menos) y No cumple"),
  Origen = c("Regiones del Banco Mundial asignadas por código de país (countrycode)",
             "INB per cápita 2019 (NY.GNP.PCAP.CD) con los umbrales del Banco Mundial del año fiscal 2021",
             "Umbral de 25 por 1.000 aplicado a la mortalidad de menores de 5 años de 2019 (SH.DYN.MORT)"),
  Uso = c("Validación independiente de los grupos",
          "Validación independiente de los grupos",
          "Lectura de los grupos frente a una meta de política pública")
)

tabla_t(
  "Variables categóricas de apoyo",
  kbl(tab_cat, format = "html", align = "l",
      col.names = c("Variable", "Categorías", "Origen", "Uso en el análisis")) %>%
    kable_styling(full_width = TRUE),
  fuente = "Fuente: elaboración propia con base en los WDI, los umbrales de ingreso del Banco Mundial (2020) y la Agenda 2030 (Naciones Unidas, 2015)."
)
Tabla 4. Variables categóricas de apoyo
Variable Categorías Origen Uso en el análisis
Región Siete regiones del Banco Mundial Regiones del Banco Mundial asignadas por código de país (countrycode) Validación independiente de los grupos
Nivel de ingreso Bajo, medio-bajo, medio-alto y alto (más sin clasificar) INB per cápita 2019 (NY.GNP.PCAP.CD) con los umbrales del Banco Mundial del año fiscal 2021 Validación independiente de los grupos
Meta ODS 3.2 (menores de 5 años) Cumple (25 por 1.000 o menos) y No cumple Umbral de 25 por 1.000 aplicado a la mortalidad de menores de 5 años de 2019 (SH.DYN.MORT) Lectura de los grupos frente a una meta de política pública
Fuente: elaboración propia con base en los WDI, los umbrales de ingreso del Banco Mundial (2020) y la Agenda 2030 (Naciones Unidas, 2015).

De las tres categorías, solo la región y el ingreso pueden contradecir al modelo; la meta ODS lo complementa. Por eso el análisis de validación de los grupos se apoya sobre todo en las dos primeras.

Base de datos del modelo

base_modelo <- paises %>%
  select(País = country_name, Código = country_code, Región = region,
         `Nivel de ingreso` = income, `Meta ODS 3.2` = Meta_ODS,
         `INB per cápita 2019 (US$, Atlas)` = INB_pc, all_of(names(vars))) %>%
  rename_with(~ unname(etiquetas[.x]), all_of(names(vars)))

archivo_base <- "base_final_mortalidad_2019.csv"
ruta_base <- tryCatch({
  write_excel_csv2(base_modelo, archivo_base)
  archivo_base
}, error = function(e) {
  tmp <- tempfile(fileext = ".csv")
  write_excel_csv2(base_modelo, tmp)
  tmp
})

tabla_t(
  "Base de datos depurada: indicadores de salud y demografía y variables de apoyo por país, 2019",
  dt(base_modelo, filtro = "top", scrollX = TRUE) %>%
    fr(unname(etiquetas[names(vars)]), 2) %>%
    fr("INB per cápita 2019 (US$, Atlas)", 0)
)
Tabla 5. Base de datos depurada: indicadores de salud y demografía y variables de apoyo por país, 2019
Fuente: elaboración propia con base en los WDI, 2019.

↓ Descargar la base completa (CSV)

La base final tiene una fila por país y reúne todas las variables del análisis: las 15 cuantitativas, las tres categóricas de apoyo (región, nivel de ingreso y meta ODS 3.2) y el INB per cápita con el que se asignó el nivel de ingreso. Las cuantitativas y el INB provienen de DataBank; el ingreso se obtiene al clasificar el INB con los umbrales del Banco Mundial; la región, del código de cada país; y la meta ODS, de la mortalidad de menores de 5 años (25 por 1.000 o menos = “Cumple”). La tabla puede ordenarse por cualquier columna, buscarse por texto y filtrarse con las cajas bajo los encabezados, y el botón descarga la misma base en un archivo CSV que también queda guardado en la carpeta del proyecto (base_final_mortalidad_2019.csv).

Esta base no se armó a mano: la genera el propio documento cada vez que se compila, a partir del archivo descargado de DataBank. Se hizo así por tres razones. La primera es la reproducibilidad: cualquier persona que ejecute este archivo con los mismos datos obtiene exactamente la misma base, la misma muestra de 162 países y los mismos resultados. La segunda es la trazabilidad: cada columna se puede seguir hasta su origen en el código, sin pasos intermedios en Excel que no queden registrados. La tercera es evitar errores manuales: copiar, pegar o filtrar datos a mano es la fuente más común de equivocaciones, como una fila corrida o un país duplicado, y al hacerlo con código ese riesgo desaparece. Por eso el archivo descargado de DataBank se conserva intacto como dato original, y todo lo que se le hace (depurar, clasificar y construir las variables de apoyo) queda escrito y a la vista en el código de esta sección.

Modelo

El análisis combina cuatro pasos encadenados: estandarización, reducción de dimensionalidad con ACP, medición de distancias entre países y clusterización jerárquica con el método de Ward. Todo se realizó en R. El esquema de trabajo (ACP, nombre de los componentes, clusterización de Ward y caracterización de los grupos) sigue el desarrollo propuesto por Joaqui Barandica (2022).

Estandarización

Las 15 variables están en unidades distintas (por 1.000, porcentajes, años) y sus varianzas son muy diferentes. Sin estandarizar, las variables con mayor escala numérica dominarían los componentes y la formación de los grupos solo por su magnitud, y no por la información que aportan. Por eso cada variable se transforma en un puntaje z:

\[z_{ij}=\frac{x_{ij}-\bar{x}_j}{s_j}\]

donde \(x_{ij}\) es el valor de la variable \(j\) en el país \(i\), \(\bar{x}_j\) es su media y \(s_j\) su desviación estándar. Con esta transformación todas las variables tienen media 0 y varianza 1, y contribuyen en igualdad de condiciones.

vv <- apply(X, 2, var)
d_var <- tibble(Variable = unname(etiquetas[names(vv)]), Original = vv, Estandarizada = 1) %>%
  arrange(Original) %>%
  mutate(Variable = factor(Variable, levels = Variable))

plot_ly(d_var, y = ~Variable, x = ~Original, type = "bar", orientation = "h",
        name = "Varianza original", marker = list(color = "#52b788"),
        hovertemplate = "%{y}<br>Varianza original: %{x:,.1f}<extra></extra>", height = 560) %>%
  add_bars(x = ~Estandarizada, name = "Varianza estandarizada", marker = list(color = "#c7a64a"),
           hovertemplate = "%{y}<br>Varianza estandarizada: %{x}<extra></extra>") %>%
  estilo("Varianza (escala logarítmica)", "",
         tit_g("Varianza de cada variable antes y después de estandarizar"),
         l = 270, b = 90, xextra = list(type = "log")) %>%
  layout(barmode = "group", legend = leyenda_h("Varianza"))
Gráfico 1. Varianza de cada variable antes y después de estandarizar
Fuente: WDI, Banco Mundial | 2019

Las barras verdes muestran que las varianzas originales difieren en varios órdenes de magnitud, mientras que tras estandarizar todas valen 1 (barras doradas). Las dos variables de mortalidad adulta concentran el 86 % de la varianza total: sin estandarizar, el ACP y Ward seguirían casi exclusivamente a esas dos variables e ignorarían el resto de los indicadores. La estandarización evita que el resultado dependa de las unidades de medida.

Análisis de Componentes Principales (ACP)

El ACP transforma un conjunto de variables correlacionadas en un conjunto menor de componentes principales, que son combinaciones lineales de las variables originales, no correlacionadas entre sí y ordenadas por la varianza que explican. El primer componente captura la mayor varianza posible; el segundo, la máxima varianza restante bajo la condición de ser ortogonal al primero, y así sucesivamente.

Con variables estandarizadas, la matriz de covarianzas coincide con la matriz de correlaciones \(\mathbf{R}\). Los componentes se obtienen de su descomposición espectral:

\[\mathbf{R}\mathbf{v}_k=\lambda_k\mathbf{v}_k\]

donde \(\lambda_k\) es el valor propio del componente \(k\) (la varianza que explica) y \(\mathbf{v}_k\) su vector propio (los pesos de cada variable). La coordenada del país \(i\) en el componente \(k\) es:

\[C_{ik}=\sum_{j=1}^{p} v_{jk} z_{ij}\]

Como la traza de \(\mathbf{R}\) es igual al número de variables \(p=15\), la suma de los valores propios es 15 y el porcentaje de varianza explicada por el componente \(k\) es \(\lambda_k/15\times 100\). La interpretación se apoya en la correlación entre cada variable y el componente, \(r(z_j,C_k)=\sqrt{\lambda_k}\; v_{jk}\), en la calidad de representación de cada variable, que es la suma de esas correlaciones al cuadrado sobre los componentes retenidos, y en la contribución de cada variable, que indica qué porcentaje de la varianza del componente aporta.

Número de componentes. Se retienen los componentes con valor propio mayor que 1 (criterio de Kaiser): un componente con \(\lambda>1\) explica más varianza que una variable estandarizada individual y por tanto resume la información de varias variables a la vez. Esta regla se contrasta con el gráfico de sedimentación, donde se busca el punto en que la curva deja de descender con fuerza, y con la varianza acumulada. Se utilizó el paquete FactoMineR. Retener pocos componentes implica descartar la varianza de los demás, por lo que siempre se reporta el porcentaje que conservan los seleccionados.

Distancia euclidiana

Con las coordenadas de los países en los \(q\) componentes retenidos, la diferencia entre dos países se mide con la distancia euclidiana:

\[d(i,l)=\sqrt{\sum_{k=1}^{q}\left(C_{ik}-C_{lk}\right)^2}\]

Distancias pequeñas indican perfiles de mortalidad, salud y demografía similares, y distancias grandes indican perfiles distintos. Como los componentes son ortogonales, esta distancia no cuenta dos veces la información compartida por variables correlacionadas, lo que la hace apropiada en este contexto.

Clusterización jerárquica aglomerativa (método de Ward)

El método de Ward parte de cada país como un grupo individual y, en cada paso, fusiona los dos grupos cuya unión produce el menor aumento de la suma de cuadrados dentro de los grupos, es decir, el que menos homogeneidad interna sacrifica. El costo de fusionar los grupos \(A\) y \(B\) es:

\[\Delta(A,B)=\frac{n_A n_B}{n_A+n_B}\ \|\bar{c}_A-\bar{c}_B\|^2\]

donde \(n_A\) y \(n_B\) son los tamaños de los grupos y \(\bar{c}_A\) y \(\bar{c}_B\) sus centroides en el espacio de componentes. El proceso termina cuando todos los países forman un solo grupo, y su historia completa se resume en un dendrograma, donde la altura de cada unión indica el costo de esa fusión. Se escogió Ward porque tiende a formar grupos compactos y de tamaño relativamente equilibrado, lo que facilita su interpretación.

En R se usó hclust con el método ward.D2, que aplica el criterio de Ward sobre distancias euclidianas elevadas al cuadrado internamente, tal como lo definió su autor. Se agrupó sobre las coordenadas de los componentes retenidos, y no sobre las variables originales, lo que además filtra el ruido de los componentes de baja varianza.

Selección del número de grupos

El dendrograma no define por sí solo el número de grupos, por lo que se combinan cuatro criterios:

  • Altura de fusión: un salto grande al unir dos grupos indica que se están juntando perfiles muy distintos.
  • Índice de silueta: mide qué tan bien separado está cada país de los grupos vecinos.
  • Tamaño de los grupos: un grupo con un solo país no describe un perfil común sino un caso atípico.
  • Interpretabilidad: los grupos deben ser sustantivamente distinguibles.

El índice de silueta compara, para cada país, la distancia media a su propio grupo (\(a_i\)) con la distancia media al grupo más cercano (\(b_i\)):

\[s_i=\frac{b_i-a_i}{\max(a_i, b_i)}\]

Valores cercanos a 1 indican países bien ubicados en su grupo, y valores cercanos a 0 o negativos, ubicación dudosa. Como regla de lectura, una silueta media superior a 0,5 indica una estructura razonable.

Caracterización y validación de los grupos

Los grupos se ordenan de menor a mayor esperanza de vida promedio. Cada uno se describe con el promedio de las 15 variables y con el valor test (v-test), que mide cuántas desviaciones estándar se aleja el promedio del grupo del promedio global, y se contrasta con las variables categóricas de apoyo, que no intervinieron en su construcción. Si grupos formados solo con indicadores de salud y demografía coinciden con esas clasificaciones externas, hay evidencia de que la segmentación es coherente. Siguiendo a la práctica habitual, los componentes y los grupos se nombran a partir de las variables que los definen para facilitar su interpretación.

Por último, se evalúa la estabilidad de la segmentación: el agrupamiento se repite cambiando decisiones del análisis (número de componentes, variables incluidas, presencia del país más atípico y algoritmo) y cada resultado se compara con la solución principal mediante el índice de Rand ajustado.

Síntesis del procedimiento

sintesis <- tibble(
  Etapa = c("1. Preparación", "2. Descriptivo", "3. Reducción de dimensionalidad",
            "4. Segmentación", "5. Número de grupos", "6. Caracterización y validación"),
  Procedimiento = c("Casos completos y estandarización (puntaje z)",
                    "Estadísticos, distribuciones, relaciones y matriz de correlaciones",
                    "Análisis de Componentes Principales con criterio de Kaiser",
                    "Clusterización jerárquica de Ward sobre los componentes retenidos",
                    "Altura de fusión, índice de silueta y tamaño de los grupos",
                    "Promedios, valores test, contraste con ingreso y región, y estabilidad (Rand ajustado)"),
  Herramienta = c("tidyverse, janitor, countrycode", "plotly, DT", "FactoMineR", "hclust (ward.D2)", "cluster, plotly", "FactoMineR, plotly")
)

tabla_t(
  "Resumen del procedimiento analítico",
  kbl(sintesis, format = "html", align = "l",
      col.names = c("Etapa", "Procedimiento", "Herramienta en R")) %>%
    kable_styling(full_width = TRUE),
  fuente = "Fuente: elaboración propia."
)
Tabla 6. Resumen del procedimiento analítico
Etapa Procedimiento Herramienta en R
1. Preparación Casos completos y estandarización (puntaje z) tidyverse, janitor, countrycode
2. Descriptivo Estadísticos, distribuciones, relaciones y matriz de correlaciones plotly, DT
3. Reducción de dimensionalidad Análisis de Componentes Principales con criterio de Kaiser FactoMineR
4. Segmentación Clusterización jerárquica de Ward sobre los componentes retenidos hclust (ward.D2)
5. Número de grupos Altura de fusión, índice de silueta y tamaño de los grupos cluster, plotly
6. Caracterización y validación Promedios, valores test, contraste con ingreso y región, y estabilidad (Rand ajustado) FactoMineR, plotly
Fuente: elaboración propia.

Cada etapa usa el resultado de la anterior: las coordenadas del ACP alimentan la clusterización, y los grupos resultantes se validan con variables que no entraron al modelo.

Alcance y limitaciones metodológicas

  • Es un corte transversal de un solo año, por lo que no recoge la evolución de los países.
  • Se trabaja con casos completos, de modo que quedan fuera territorios, microestados y algunos países con datos incompletos.
  • Varios indicadores del Banco Mundial son estimaciones modeladas y no mediciones directas, sobre todo en países con sistemas estadísticos débiles.
  • El ACP supone relaciones lineales entre variables, y el método de Ward es sensible al número de grupos elegido y a los países atípicos.
  • La desnutrición está truncada en 2,5 % para los países con baja prevalencia, lo que reduce su variabilidad en el extremo bajo.

Resultados descriptivos

Antes de modelar se examinan los datos con tablas y gráficos. El objetivo es entender cómo se comportan los 15 indicadores y las tres variables de apoyo, detectar valores atípicos y asimetrías que condicionan el análisis, y anticipar qué patrones debería recoger el ACP.

Estadísticas descriptivas

La tabla resume cada variable con su número de países, su media y mediana, su dispersión (desviación estándar y coeficiente de variación), su rango y su asimetría. Comparar la media con la mediana y mirar el signo de la asimetría permite saber si la distribución está equilibrada o si unos pocos países con valores extremos la jalan hacia un lado.

desc <- paises %>%
  select(all_of(names(vars))) %>%
  pivot_longer(everything(), names_to = "var") %>%
  group_by(var) %>%
  summarise(N = n(), Media = mean(value), Mediana = median(value), DE = sd(value),
            Mínimo = min(value), Máximo = max(value),
            CV = 100 * sd(value) / mean(value),
            Asimetría = mean(((value - mean(value)) / sd(value))^3),
            .groups = "drop") %>%
  left_join(dim_tab, by = "var") %>%
  mutate(Variable = unname(etiquetas[var])) %>%
  arrange(match(var, unlist(dimensiones))) %>%
  select(Dimensión = Dimension, Variable, N, Media, Mediana, DE, Mínimo, Máximo,
         `CV (%)` = CV, Asimetría, var)

tabla_t(
  "Estadísticos descriptivos de las variables cuantitativas",
  dt(select(desc, -var), n = 15, scrollX = TRUE) %>%
    fr(c("Media", "Mediana", "DE", "Mínimo", "Máximo", "CV (%)", "Asimetría"), 2)
)
Tabla 7. Estadísticos descriptivos de las variables cuantitativas
Fuente: elaboración propia con base en los WDI, 2019.

La variable más dispersa en términos relativos es mortalidad de menores de 5 años, con un coeficiente de variación de 114,48 %, y la más homogénea es esperanza de vida al nacer (11,15 %). Las mortalidades, la desnutrición y la fecundidad tienen asimetría positiva: la mayoría de los países está en valores bajos y una minoría con mortalidad muy alta eleva la media por encima de la mediana. Lo contrario ocurre con la esperanza de vida, la vacunación DPT y el porcentaje de muertes no transmisibles, con asimetría negativa: casi todos los países están en valores altos y unos pocos quedan muy rezagados.

Esta heterogeneidad de escalas, rangos y formas confirma que los indicadores no son comparables entre sí tal como vienen, y refuerza la decisión de estandarizarlos antes del ACP.

Detrás de los coeficientes de variación hay una idea importante: un CV alto significa que la desviación estándar es una fracción grande de la media, es decir, que los países son muy distintos entre sí y que el “país promedio” es un mal resumen. En las variables con cola derecha, como las mortalidades, la media está inflada por pocos países, así que la mediana describe mejor al país típico. Por eso, más adelante, los promedios por grupo serán mucho más informativos que un promedio global.

Explorador interactivo de indicadores

En lugar de presentar los 15 indicadores a la vez, el explorador permite elegir uno con los botones. Para cada indicador se muestran sus estadísticas globales, su distribución (el histograma incluye una línea punteada dorada con la mediana), su comparación entre niveles de ingreso y los diez países con mayor y menor valor, coloreados por nivel de ingreso. Debajo de los gráficos aparece una lectura en cuatro partes: la distribución, la comparación frente al ingreso, qué significa el indicador y qué revelan sus casos extremos, y la posición de Colombia.

La comparación frente al ingreso merece una explicación. Para cada indicador se ajustó una recta de regresión contra el logaritmo del INB per cápita; se usa el logaritmo porque un dólar adicional cambia mucho la salud de un país pobre y casi nada la de uno rico. La distancia de cada país a esa recta, el residuo, indica si el indicador es mejor o peor de lo que su ingreso haría esperar. Esos países son los más interesantes del análisis, porque muestran lo que la política sanitaria logra, o deja de lograr, más allá de la riqueza.

fx <- function(v) if (v == "Fecundidad") f2 else f1

tarjetas <- function(x, v) {
  ff <- fx(v)
  vals <- list(Media = ff(mean(x)), Mediana = ff(median(x)), `Desv. estándar` = ff(sd(x)),
               Mínimo = ff(min(x)), Máximo = ff(max(x)),
               `Coef. de variación` = paste0(f2(100 * sd(x) / mean(x)), " %"))
  div(class = "stat-cards",
      lapply(names(vals), function(n) div(class = "stat-card", div(class = "stat-val", vals[[n]]),
                                          div(class = "stat-lab", n))))
}

hist_var <- function(v) {
  med <- median(paises[[v]])
  plot_ly(x = paises[[v]], type = "histogram", nbinsx = 16, height = 360,
          marker = list(color = "#52b788", line = list(color = "#ffffff", width = 1.2)),
          hovertemplate = "Intervalo: %{x}<br>Países: %{y}<extra></extra>") %>%
    estilo(unidades[[v]], "Número de países",
           tit_p("Distribución entre países"),
           l = 75, b = 75, t = 60) %>%
    layout(shapes = list(list(type = "line", x0 = med, x1 = med, y0 = 0, y1 = 1, yref = "paper",
                              line = list(color = "#c7a64a", dash = "dash", width = 2))))
}

box_var <- function(v) {
  plot_ly(paises, x = ~income, y = paises[[v]], color = ~income, colors = pal_ingreso,
          type = "box", text = ~country_name, hoverinfo = "y+text", boxpoints = "outliers",
          showlegend = FALSE, height = 360) %>%
    estilo("Nivel de ingreso", unidades[[v]],
           tit_p("Según nivel de ingreso"),
           l = 80, b = 85, t = 60)
}

barras_top <- function(v, alto = TRUE) {
  ff <- fx(v)
  d <- paises %>%
    arrange(if (alto) desc(.data[[v]]) else .data[[v]]) %>%
    slice_head(n = 10) %>%
    transmute(pais = country_name, valor = .data[[v]], income)
  d$pais <- factor(d$pais, levels = d$pais)
  plot_ly(d, x = ~valor, y = ~pais, type = "bar", orientation = "h", height = 400,
          text = ff(d$valor), textposition = "outside", cliponaxis = FALSE,
          marker = list(color = unname(pal_ingreso[as.character(d$income)])),
          hovertemplate = "%{y}<br>%{x}<extra></extra>") %>%
    estilo(unidades[[v]], "",
           tit_p(if (alto) "Diez países con mayor valor" else "Diez países con menor valor"),
           l = 170, b = 75, t = 60,
           xextra = list(range = c(0, max(d$valor) * 1.18)),
           yextra = list(autorange = "reversed"))
}


log_inb <- log(paises$INB_pc)
vp <- function(cod, v) paises[[v]][paises$country_code == cod]
lista_y <- function(x) if (length(x) == 1) x else paste0(paste(head(x, -1), collapse = ", "), " y ", tail(x, 1))
med_ing <- function(x, nivel) median(x[paises$income == nivel])

frente_ingreso <- function(v) {
  x <- paises[[v]]
  r <- cor(x, log_inb, use = "complete.obs")
  res <- residuals(lm(x ~ log_inb, na.action = na.exclude))
  arriba <- paises$country_name[order(res, decreasing = TRUE)][1:3]
  abajo <- paises$country_name[order(res)][1:3]
  paste0("<b>Frente al ingreso.</b> La correlación con el logaritmo del INB per cápita es de ", f2(r),
         ": el ingreso se asocia con cerca del ", f0(100 * r^2), " % de las diferencias entre países en este indicador. ",
         "Los países con valores más altos de lo que predice su ingreso son ", lista_y(arriba),
         ", y los que tienen valores más bajos de lo esperado, ", lista_y(abajo), ".")
}

les <- 100 - paises$Muerte_Transmis - paises$Muerte_NoTransmis
rat_mf <- paises$Mort_Adulta_Masc / paises$Mort_Adulta_Fem
sh_inf <- paises$Mort_Infantil / paises$Mort_Menores5
lac <- paises %>% filter(region == "América Latina y el Caribe") %>% arrange(desc(Esperanza_Vida))
pos_col_lac <- which(lac$country_code == "COL")

fondo <- function(v) {
  x <- paises[[v]]
  switch(v,
    Mort_Menores5 = paste0(
      "Es el indicador con el que la Agenda 2030 mide la meta ODS 3.2, y reúne muertes en su mayoría evitables: neumonía, diarrea, malaria, complicaciones del parto y desnutrición. Por eso responde más a la atención primaria, el agua potable, la vacunación y la atención del parto que a la tecnología hospitalaria. ",
      "Lo que más pesa es la cola derecha: ", sum(x > 100), " países superan las 100 muertes por 1.000, es decir, más de uno de cada diez niños no llega a cumplir cinco años, y en República Centroafricana la proporción es de uno de cada ",
      f0(1000 / vp("CAF", v)), ". La mediana de los países (", f1(median(x)), ") es muy inferior a la tasa mundial de 38 por 1.000 que reporta el UN IGME para 2019, porque la tasa mundial pondera por nacimientos y una gran parte de los niños del mundo nace en los países con mortalidad más alta. ",
      "Entre los países con menos mortalidad de la que predice su ingreso aparecen Kirguistán y Ucrania, antiguas repúblicas soviéticas que heredaron redes extensas de atención primaria; Siria también figura, pero en un país en guerra la cifra es una estimación modelada y debe leerse con cautela."),
    Mort_Infantil = paste0(
      "Comparada con la mortalidad de menores de 5 años, esta variable revela <i>cuándo</i> mueren los niños. En los países de ingreso alto, cerca del ",
      f0(100 * med_ing(sh_inf, "Alto")), " % de las muertes antes de los cinco años ocurre en el primer año de vida, sobre todo alrededor del parto, por prematuridad o malformaciones, causas difíciles de evitar. ",
      "En los de ingreso bajo esa proporción baja a cerca del ", f0(100 * med_ing(sh_inf, "Bajo")),
      " %: muchos niños sobreviven al primer año y mueren después, cuando dejan la lactancia y quedan expuestos a la malaria, la diarrea y la desnutrición. ",
      "La diferencia entre las dos mortalidades mide, por tanto, los riesgos del entorno más que los del parto, y es allí donde el agua, la nutrición y los mosquiteros tienen más efecto."),
    Tasa_Mortalidad = paste0(
      "Es la única de las 15 variables que prácticamente no se relaciona con el ingreso, y la razón es demográfica: divide las muertes entre toda la población, así que depende tanto del riesgo de morir como de cuántas personas mayores hay. ",
      "Los valores más bajos del mundo no están en los países más sanos, sino en Emiratos Árabes Unidos, Kuwait, Omán y Arabia Saudí, cuya población está formada en buena parte por trabajadores migrantes en edad laboral. ",
      "Los más altos, después de República Centroafricana, están en Europa del Este (Bulgaria, Serbia, Letonia), que combina envejecimiento con una mortalidad masculina adulta elevada. ",
      "Por eso los demógrafos no comparan la salud de dos países con la tasa bruta, sino con la esperanza de vida o con tasas ajustadas por edad, y por eso esta variable termina formando su propio componente en el ACP."),
    Mort_Adulta_Masc = paste0(
      "Mide el riesgo de morir en la edad productiva, entre los 15 y los 60 años, donde pesan las enfermedades cardiovasculares, el VIH, el alcohol, la violencia y los accidentes. ",
      "Los hombres mueren más que las mujeres en ", sum(rat_mf > 1), " de los ", length(x), " países, y la brecha es máxima en ",
      lista_y(paises$country_name[order(rat_mf, decreasing = TRUE)][1:4]),
      ", donde un hombre tiene alrededor de tres veces el riesgo de una mujer de morir antes de los 60, un patrón asociado al consumo de alcohol y a la enfermedad cardiovascular. ",
      "Los países del sur de África, como Esuatini, Namibia, Sudáfrica y Zimbabue, tienen mucha más mortalidad adulta de la que predice su ingreso: es la huella de la epidemia de VIH, que golpea justamente a la población en edad de trabajar y, con ella, a la economía."),
    Mort_Adulta_Fem = paste0(
      "Es menor que la masculina en todos los países, pero su gradiente con el ingreso es más empinado: entre los países de ingreso alto y los de ingreso bajo la mediana se multiplica por ",
      f1(med_ing(x, "Bajo") / med_ing(x, "Alto")), ", frente a ",
      f1(med_ing(paises$Mort_Adulta_Masc, "Bajo") / med_ing(paises$Mort_Adulta_Masc, "Alto")), " en los hombres. ",
      "La diferencia se explica porque en los países pobres a los riesgos comunes se suman la mortalidad materna y, en África Subsahariana, el VIH, que afecta más a las mujeres jóvenes. ",
      "Dicho de otro modo, la desventaja de nacer en un país pobre es todavía mayor para una mujer que para un hombre."),
    Muerte_Transmis = paste0(
      "Es la medida más directa de la transición epidemiológica. En la mediana de los países de ingreso bajo, más de la mitad de las muertes se debe a causas transmisibles, maternas, perinatales o nutricionales, y en Chad, Nigeria y Níger son dos de cada tres. ",
      "Lo más llamativo son los países con más carga de la que predice su ingreso: Botsuana, Gabón y Namibia, de ingreso medio-alto, conservan perfiles casi tan infecciosos como los de ingreso bajo por el VIH y la tuberculosis. ",
      "Es una muestra de que el crecimiento económico no se convierte por sí solo en salud: sin programas específicos, un país puede enriquecerse y seguir muriendo de enfermedades del pasado."),
    Muerte_NoTransmis = paste0(
      "Es el espejo de la anterior, pero exige cuidado porque es una proporción y no un riesgo. Que en Macedonia del Norte, Bulgaria o Bosnia y Herzegovina más del 95 % de las muertes sea por enfermedades no transmisibles no significa que allí estas enfermedades maten más que en otros lugares, sino que las demás causas casi desaparecieron y la población envejeció. ",
      "A escala mundial, estas enfermedades causan el 74 % de las muertes. ",
      "Lo que no suman esta variable y la anterior corresponde a las <b>lesiones</b> (accidentes, homicidios y suicidios), que no se incluyeron en el modelo: en la mediana de los países son el ", f1(median(les)),
      " % de las muertes, pero en ", lista_y(paises$country_name[order(les, decreasing = TRUE)][1:4]), " superan el 20 %."),
    Esperanza_Vida = paste0(
      "Es la variable más asociada con el ingreso, pero la relación es curva: cada dólar adicional aumenta mucho la esperanza de vida en los países pobres y casi nada en los ricos, un patrón conocido como curva de Preston. Por eso el análisis usa el logaritmo del ingreso. ",
      "Entre ", paises$country_name[which.max(x)], " y ", paises$country_name[which.min(x)], " hay ", f0(max(x) - min(x)),
      " años de diferencia, aunque el valor de República Centroafricana es tan extremo que probablemente refleja una estimación modelada en un contexto de crisis; frente a Chad o Nigeria, los siguientes, la brecha sigue siendo de más de 30 años. ",
      "Por debajo de lo que predice su ingreso están Nigeria, Esuatini y Namibia, donde el VIH y la mortalidad infantil restan años de vida."),
    Tasa_Natalidad = paste0(
      "Depende de la fecundidad y de la estructura por edades: un país con muchas mujeres jóvenes mantiene una natalidad alta aunque cada una tenga pocos hijos, un efecto que los demógrafos llaman <i>inercia demográfica</i>. ",
      "Israel es el caso atípico más claro entre los países ricos, con una natalidad de ", f1(vp("ISR", v)), " por 1.000 y una fecundidad cercana a tres hijos. ",
      "En el extremo bajo, Corea del Sur registra ", f1(vp("KOR", v)), " nacimientos por 1.000 habitantes, menos de una séptima parte que Somalia (", f1(vp("SOM", v)), ")."),
    Fecundidad = paste0(
      "El umbral clave es 2,1 hijos por mujer, el <i>nivel de reemplazo</i>: por debajo de él, cada generación es más pequeña que la anterior. ",
      sum(x < 2.1), " de los ", length(x), " países ya están por debajo. Corea del Sur, con ", f2(vp("KOR", v)),
      ", tiene la fecundidad más baja de la muestra: cada generación será menos de la mitad de la de sus padres. En Somalia, Níger y Chad, en cambio, las mujeres tienen en promedio más de seis hijos. ",
      "Nepal, India y Myanmar tienen una fecundidad mucho menor de la que predice su ingreso, lo que muestra que la educación de las mujeres y el acceso a planificación familiar pueden adelantar la transición sin esperar al crecimiento económico."),
    Pob_0a14 = paste0(
      "Mide la dependencia juvenil. En República Centroafricana, Níger y Chad casi la mitad de la población es menor de 15 años, lo que obliga a destinar gran parte de los recursos a escuelas, vacunas y atención materno-infantil con relativamente pocos adultos que generen ingresos. ",
      "Cuando la fecundidad cae, esta proporción baja y se abre el llamado <i>bono demográfico</i>: durante algunas décadas hay muchas personas en edad de trabajar y pocos dependientes, una ventana de oportunidad para ahorrar e invertir que se cierra cuando la población envejece."),
    Pob_65mas = paste0(
      "Japón, con ", f1(vp("JPN", v)), " %, es el país más envejecido de la muestra. Los países del Golfo están entre los valores más bajos aunque sean ricos, porque buena parte de su población son trabajadores migrantes que regresan a su país antes de envejecer. ",
      "En Europa del Este, en cambio, el envejecimiento supera lo que predice el ingreso, por la combinación de fecundidad muy baja y emigración de jóvenes. ",
      "El envejecimiento es la cara inevitable del éxito sanitario y anticipa el gran reto fiscal de los países avanzados: pensiones, cuidado y atención de enfermedades crónicas."),
    Gasto_Salud = paste0(
      "Mide el <i>esfuerzo</i> y no el <i>monto</i>: al estar en porcentaje del PIB, un país pobre puede tener un porcentaje alto con muy poco dinero por persona. Afganistán aparece segundo en la muestra, con ", f1(vp("AFG", v)),
      " %, porque su PIB es pequeño y gran parte del gasto sale del bolsillo de los hogares y de la ayuda internacional. ",
      "Estados Unidos (", f1(vp("USA", v)), " %) gasta casi el doble que los demás países ricos y aun así tiene una esperanza de vida de ", f1(vp("USA", "Esperanza_Vida")),
      " años, frente a ", f1(vp("JPN", "Esperanza_Vida")), " en Japón. En el otro extremo, Luxemburgo, Emiratos Árabes Unidos y Omán gastan poco en proporción porque su PIB es muy grande. ",
      "Por todo esto el gasto se relaciona poco con los resultados y queda mal representado en los componentes."),
    Desnutricion = paste0(
      "Es la variable con mayor distorsión de medición: ", sum(x <= 2.5), " países aparecen con el valor truncado de 2,5 %, de modo que no se distingue entre un país con 2,4 % y otro con 0,1 %. ",
      "En la cola alta, en Somalia más de la mitad de la población no consume la energía mínima, y Haití (", f1(vp("HTI", v)), " %) es el único país de América entre los diez peores. ",
      "Importa más de lo que parece porque la desnutrición es la causa subyacente de buena parte de las muertes infantiles por infecciones: un niño desnutrido muere de una diarrea que un niño bien alimentado supera."),
    Vacunacion_DPT = paste0(
      "La tercera dosis de la vacuna DPT se usa en el mundo como termómetro de la atención primaria: exige que el niño vuelva tres veces al servicio de salud, así que mide la continuidad del contacto con el sistema y no solo su existencia. ",
      "Casi todos los países superan el 85 %, pero Papúa Nueva Guinea (", f0(vp("PNG", v)), " %) y República Centroafricana (", f0(vp("CAF", v)), " %) dejan sin proteger a más de seis de cada diez niños. ",
      "Ruanda, Malaui y Sierra Leona superan con creces lo que predice su ingreso: con programas focalizados y apoyo internacional, alcanzan coberturas de país rico con recursos de país pobre. Por eso su correlación con el ingreso es de las más bajas."),
    "")
}

col_extra <- function(v) {
  switch(v,
    Mort_Menores5 = "Está por debajo del umbral de 25 de la meta ODS 3.2.",
    Mort_Infantil = paste0("El ", f0(100 * sh_inf[paises$country_code == "COL"]), " % de sus muertes de menores de 5 años ocurre en el primer año, un patrón propio de los países que ya controlaron buena parte de las infecciones."),
    Tasa_Mortalidad = "Es una de las más bajas del mundo, no porque Colombia sea más sana que Japón, sino porque su población es más joven.",
    Mort_Adulta_Masc = paste0("Un hombre colombiano tiene ", f1(rat_mf[paises$country_code == "COL"]), " veces el riesgo de una mujer de morir entre los 15 y los 60 años; en América Latina esa brecha se explica sobre todo por la violencia y los accidentes de tránsito."),
    Muerte_NoTransmis = paste0("Las lesiones causan el ", f1(les[paises$country_code == "COL"]), " % de sus muertes, el puesto ", sum(les > les[paises$country_code == "COL"]) + 1, " de ", length(les), ": es el rasgo que más separa a Colombia de los países con su mismo nivel de salud."),
    Esperanza_Vida = paste0("Ocupa el puesto ", pos_col_lac, " en América Latina y el Caribe, detrás de ", lista_y(head(lac$country_name, pos_col_lac - 1)), "."),
    Fecundidad = "Está por debajo del nivel de reemplazo: su bono demográfico ya tiene fecha de cierre.",
    Pob_65mas = "Es una proporción todavía moderada, pero con una fecundidad por debajo del reemplazo crecerá rápido en las próximas décadas.",
    Gasto_Salud = "Gasta más en salud, como proporción del PIB, que la mediana de los países de ingreso medio-alto.",
    "")
}

nota_col <- function(v) {
  x <- paises[[v]]
  ff <- fx(v)
  vc <- vp("COL", v)
  paste0("<b>Colombia.</b> Registra ", ff(vc), " (", unidades[[v]], "), en el puesto ", sum(x > vc) + 1, " de ", length(x),
         " de mayor a menor; la mediana de los países es ", ff(median(x)), ". ", col_extra(v))
}

texto_var <- function(v) {
  x <- paises[[v]]
  ff <- fx(v)
  sk <- mean(((x - mean(x)) / sd(x))^3)
  forma <- if (sk > 0.5) "asimetría positiva, con cola hacia valores altos"
           else if (sk < -0.5) "asimetría negativa, con cola hacia valores bajos"
           else "una forma aproximadamente simétrica"
  rel <- if (mean(x) > median(x)) "supera" else "es inferior a"
  mb <- med_ing(x, "Bajo")
  ma <- med_ing(x, "Alto")
  p1 <- paste0("<b>Distribución.</b> Presenta ", forma, ": la media (", ff(mean(x)), ") ", rel, " la mediana (", ff(median(x)), "). ",
               "El valor más alto corresponde a ", paises$country_name[which.max(x)], " (", ff(max(x)), ") y el más bajo a ",
               paises$country_name[which.min(x)], " (", ff(min(x)), "). Según el nivel de ingreso, la mediana pasa de ",
               ff(mb), " en los países de ingreso bajo a ", ff(ma), " en los de ingreso alto.")
  paste0("<p>", p1, "</p><p>", frente_ingreso(v), "</p><p><b>Qué significa.</b> ", fondo(v), "</p>",
         "<p class=\"col-nota\">", nota_col(v), "</p>")
}

panel_var <- function(v, visible) {
  div(class = "vpanel", id = paste0("vp-", v), style = if (visible) "" else "display:none;",
      p(class = "vdesc", tags$b(etiquetas[[v]]), " — ", definiciones[[v]], ". Dimensión: ",
        dim_tab$Dimension[dim_tab$var == v], "."),
      div(class = "vsub", "Estadísticas globales"),
      tarjetas(paises[[v]], v),
      div(class = "vsub", "Distribución y comparación por nivel de ingreso"),
      div(class = "grid-graf", style = "grid-template-columns: repeat(2, minmax(0, 1fr));",
          hist_var(v), box_var(v)),
      div(class = "vsub", "Países en los extremos"),
      div(class = "grid-graf", style = "grid-template-columns: repeat(2, minmax(0, 1fr));",
          barras_top(v, TRUE), barras_top(v, FALSE)),
      div(class = "lectura", HTML(texto_var(v))))
}

todas <- unlist(dimensiones)

botones_var <- lapply(names(dimensiones), function(d) {
  vs <- dimensiones[[d]]
  div(class = "vgrupo",
      div(class = "vgrupo-titulo", d),
      div(class = "vbtns",
          lapply(vs, function(v) {
            tags$button(type = "button", class = paste("vbtn", if (v == todas[1]) "activo"),
                        `data-target` = paste0("vp-", v), etiquetas[[v]])
          })))
})

tagList(botones_var, lapply(todas, function(v) panel_var(v, v == todas[1])))
Mortalidad y longevidad
Perfil epidemiológico
Estructura demográfica
Sistema de salud y determinantes

Mortalidad de menores de 5 años — Probabilidad de morir antes de los 5 años (por 1.000 nacidos vivos) . Dimensión: Mortalidad y longevidad .

Estadísticas globales
29,1
Media
15,8
Mediana
33,4
Desv. estándar
2,4
Mínimo
254,7
Máximo
114,48 %
Coef. de variación
Distribución y comparación por nivel de ingreso
Países en los extremos

Distribución. Presenta asimetría positiva, con cola hacia valores altos: la media (29,1) supera la mediana (15,8). El valor más alto corresponde a República Centroafricana (254,7) y el más bajo a Finlandia (2,4). Según el nivel de ingreso, la mediana pasa de 74,0 en los países de ingreso bajo a 4,0 en los de ingreso alto.

Frente al ingreso. La correlación con el logaritmo del INB per cápita es de -0,72: el ingreso se asocia con cerca del 51 % de las diferencias entre países en este indicador. Los países con valores más altos de lo que predice su ingreso son República Centroafricana, Nigeria y Chad, y los que tienen valores más bajos de lo esperado, Kirguistán, Siria y Nicaragua.

Qué significa. Es el indicador con el que la Agenda 2030 mide la meta ODS 3.2, y reúne muertes en su mayoría evitables: neumonía, diarrea, malaria, complicaciones del parto y desnutrición. Por eso responde más a la atención primaria, el agua potable, la vacunación y la atención del parto que a la tecnología hospitalaria. Lo que más pesa es la cola derecha: 7 países superan las 100 muertes por 1.000, es decir, más de uno de cada diez niños no llega a cumplir cinco años, y en República Centroafricana la proporción es de uno de cada 4. La mediana de los países (15,8) es muy inferior a la tasa mundial de 38 por 1.000 que reporta el UN IGME para 2019, porque la tasa mundial pondera por nacimientos y una gran parte de los niños del mundo nace en los países con mortalidad más alta. Entre los países con menos mortalidad de la que predice su ingreso aparecen Kirguistán y Ucrania, antiguas repúblicas soviéticas que heredaron redes extensas de atención primaria; Siria también figura, pero en un país en guerra la cifra es una estimación modelada y debe leerse con cautela.

Colombia. Registra 13,5 (muertes por 1.000 nacidos vivos), en el puesto 96 de 162 de mayor a menor; la mediana de los países es 15,8. Está por debajo del umbral de 25 de la meta ODS 3.2.

r_ing <- sapply(names(vars), function(v) cor(paises[[v]], log_inb, use = "complete.obs"))
orden_r <- sort(abs(r_ing), decreasing = TRUE)

Al recorrer los 15 indicadores aparecen tres patrones que vale la pena dejar escritos, porque reaparecen en todo el resto del análisis.

El ingreso importa, pero no lo explica todo. La variable más ligada al ingreso es la población de 0 a 14 años (r = -0,85) y la menos ligada, la tasa bruta de mortalidad (r = 0,01). En 4 de los 15 indicadores el ingreso se asocia con menos de la mitad de las diferencias entre países (r² < 0,49): la otra mitad depende de decisiones de política, de la historia de cada sistema de salud o de choques como las epidemias y los conflictos.

Los mismos países se repiten en los extremos. República Centroafricana, Chad, Níger, Nigeria y Somalia ocupan la cola desfavorable de casi todas las variables, y Japón, los países nórdicos y Europa del Sur la favorable. Que un país sea extremo en muchos indicadores a la vez es una primera señal de que las variables miden un mismo fenómeno de fondo, que es lo que el ACP confirmará.

Las sorpresas tienen explicación. Los países del sur de África, ricos para su región, tienen mortalidades adultas y cargas infecciosas propias de países pobres por el VIH; los del Golfo tienen tasas brutas de mortalidad bajísimas por su población migrante joven; y varias antiguas repúblicas soviéticas tienen indicadores infantiles mejores que los que su ingreso predice. Ningún indicador aislado basta para describir a un país, y por eso el trabajo los combina.

Análisis por dimensiones

Las 15 variables pertenecen a cuatro dimensiones. Para compararlas en una misma escala, cada indicador se estandarizó y se calculó su promedio por nivel de ingreso: un valor de 0 equivale al promedio de todos los países, y un valor de 1, a una desviación estándar por encima. Cada pestaña corresponde a una dimensión.

Zs <- as.data.frame(scale(X))
Zs$income <- paises$income

z_dim <- function(d) {
  vs <- dimensiones[[d]]
  Zs %>%
    pivot_longer(all_of(vs), names_to = "var", values_to = "z") %>%
    group_by(income, var) %>%
    summarise(z = mean(z), .groups = "drop") %>%
    mutate(Variable = factor(unname(etq_corta[var]), levels = unname(etq_corta[vs])))
}

graf_dim <- function(d) {
  plot_ly(z_dim(d), x = ~Variable, y = ~z, color = ~income, colors = pal_ingreso, type = "bar",
          height = 500,
          hovertemplate = "%{x}<br>Ingreso %{fullData.name}: %{y:.2f} desv. est.<extra></extra>") %>%
    estilo("", "Promedio estandarizado (desviaciones estándar)",
           tit_g(paste0("Dimensión «", tolower(d), "» según nivel de ingreso")),
           l = 90, b = 90,
           xextra = list(tickangle = -20), yextra = list(zeroline = TRUE, zerolinecolor = "#9aa89f")) %>%
    layout(barmode = "group", legend = leyenda_h("Nivel de ingreso"))
}

texto_dim <- function(d) {
  t <- z_dim(d) %>%
    filter(income %in% c("Bajo", "Alto")) %>%
    select(income, var, z) %>%
    pivot_wider(names_from = income, values_from = z) %>%
    mutate(dif = Alto - Bajo) %>%
    arrange(desc(abs(dif)))
  paste0("La mayor distancia entre los países de ingreso bajo y los de ingreso alto se da en ",
         bajo(unname(etiquetas[t$var[1]])), " (", f1(abs(t$dif[1])), " desviaciones estándar) y la menor en ",
         bajo(unname(etiquetas[t$var[nrow(t)]])), " (", f1(abs(t$dif[nrow(t)])), ").")
}

Mortalidad y longevidad

Esta dimensión reúne las seis variables que miden cuánto y a qué edades se muere. Las barras de las mortalidades y de la esperanza de vida deberían apuntar en sentidos opuestos si el ingreso se asocia con la salud.

graf_dim("Mortalidad y longevidad")
Gráfico 2. Dimensión «mortalidad y longevidad» según nivel de ingreso
Fuente: WDI, Banco Mundial | 2019

La mayor distancia entre los países de ingreso bajo y los de ingreso alto se da en esperanza de vida al nacer (2,4 desviaciones estándar) y la menor en tasa bruta de mortalidad (0,2). Las mortalidades se alejan de la media hacia arriba en los países de ingreso bajo y hacia abajo en los de ingreso alto, mientras que la esperanza de vida hace lo contrario. La tasa bruta de mortalidad es la excepción: casi no varía con el ingreso, porque depende de la estructura por edades. Ese comportamiento propio es el que más adelante define el segundo componente.

Traducido a la vida de las personas: en la mediana, un niño que nace en un país de ingreso bajo tiene 19 veces más riesgo de morir antes de los cinco años que uno que nace en un país de ingreso alto, y puede esperar vivir 20 años menos. La brecha no se limita a la infancia: un adulto de 15 años en un país de ingreso bajo tiene 3,4 veces más probabilidad de morir antes de los 60 si es hombre y 4,8 veces si es mujer.

Perfil epidemiológico

Esta dimensión solo tiene dos variables, y como son proporciones del mismo total de muertes, sus barras son espejos una de la otra.

graf_dim("Perfil epidemiológico")
Gráfico 3. Dimensión «perfil epidemiológico» según nivel de ingreso
Fuente: WDI, Banco Mundial | 2019

La mayor distancia entre los países de ingreso bajo y los de ingreso alto se da en muertes por enfermedades no transmisibles (2,4 desviaciones estándar) y la menor en muertes por enfermedades transmisibles (2,3). En los países de ingreso bajo predominan las muertes por enfermedades transmisibles, maternas, perinatales y nutricionales; a medida que sube el ingreso, el peso pasa a las enfermedades no transmisibles. Es la expresión directa de la transición epidemiológica.

Estructura demográfica

Aquí se compara cómo se renueva y cómo envejece la población: natalidad, fecundidad, población joven y población de 65 años o más.

graf_dim("Estructura demográfica")
Gráfico 4. Dimensión «estructura demográfica» según nivel de ingreso
Fuente: WDI, Banco Mundial | 2019

La mayor distancia entre los países de ingreso bajo y los de ingreso alto se da en tasa bruta de natalidad (2,5 desviaciones estándar) y la menor en población de 65 años o más (2,0). La natalidad, la fecundidad y la población joven bajan con el ingreso, y la población de 65 años o más sube. Se trata de los dos lados de la transición demográfica: los países de ingreso alto tienen pocos nacimientos y muchos adultos mayores.

Sistema de salud y determinantes

Esta dimensión reúne el gasto, la desnutrición y la cobertura de vacunación.

graf_dim("Sistema de salud y determinantes")
Gráfico 5. Dimensión «sistema de salud y determinantes» según nivel de ingreso
Fuente: WDI, Banco Mundial | 2019

La mayor distancia entre los países de ingreso bajo y los de ingreso alto se da en prevalencia de desnutrición (2,2 desviaciones estándar) y la menor en gasto corriente en salud (1,1). La desnutrición baja y la vacunación sube con el ingreso, como era de esperar. El gasto en salud aumenta, pero con una diferencia menor que la de los otros indicadores, lo que concuerda con que el esfuerzo económico por sí solo no explique los resultados de salud.

La lección de esta dimensión es que los insumos del sistema (cuánto se gasta) se relacionan menos con el ingreso que los resultados (cuántos niños se vacunan o cuántas personas comen lo suficiente). Ruanda, Malaui o Sierra Leona, de ingreso bajo, vacunan al 95 % o más de sus niños, como un país rico, porque organizaron bien su atención primaria; lo que no pueden es gastar lo mismo. Por eso, en las secciones siguientes, el gasto en salud resulta ser una de las variables peor representadas por los componentes.

Relaciones entre variables

Los diagramas de dispersión permiten ver cómo se relacionan pares de indicadores y si hay países que se apartan de la tendencia. Cada punto es un país, coloreado por nivel de ingreso; al pasar el cursor aparece su nombre y sus valores.

disp <- function(xv, yv, titulo, logy = FALSE) {
  plot_ly(paises, x = paises[[xv]], y = paises[[yv]], color = ~income, colors = pal_ingreso,
          type = "scatter", mode = "markers", text = ~country_name, height = 540,
          marker = list(size = 9, opacity = 0.85, line = list(color = "white", width = 0.8)),
          hovertemplate = paste0("<b>%{text}</b><br>", etiquetas[[xv]], ": %{x:.1f}<br>",
                                 etiquetas[[yv]], ": %{y:.1f}<extra></extra>")) %>%
    estilo(paste0(etiquetas[[xv]], " (", unidades[[xv]], ")"),
           paste0(etiquetas[[yv]], " (", unidades[[yv]], ")"),
           tit_g(titulo), l = 90, b = 90,
           yextra = if (logy) list(type = "log") else list()) %>%
    layout(legend = leyenda_h("Nivel de ingreso"))
}

Fecundidad y esperanza de vida

La transición demográfica sugiere que los países con más hijos por mujer deberían tener menor esperanza de vida.

disp("Fecundidad", "Esperanza_Vida", "Esperanza de vida y fecundidad por país")
Gráfico 6. Esperanza de vida y fecundidad por país
Fuente: WDI, Banco Mundial | 2019

La correlación entre ambas variables es de -0,84: la nube desciende de forma clara hacia la derecha. Los colores se ordenan de derecha a izquierda desde el ingreso bajo hasta el alto, de modo que la posición en la transición demográfica se asocia con el ingreso, aunque los niveles intermedios se traslapan. Esta relación fuerte entre dos variables de dimensiones distintas es la razón de fondo por la que un solo componente puede resumirlas.

Una correlación de -0,84 equivale a un r² de 71 %: esa proporción de las diferencias en esperanza de vida entre países se asocia con diferencias en fecundidad. No significa que una cause la otra; ambas responden a factores comunes, como el acceso a servicios de salud, la educación de las mujeres y el nivel de desarrollo.

Mortalidad infantil y gasto en salud

Si gastar más en salud bastara para reducir la mortalidad, los países con mayor gasto deberían tener menor mortalidad infantil. El eje vertical está en escala logarítmica para distinguir mejor a los países con mortalidad baja.

disp("Gasto_Salud", "Mort_Infantil", "Mortalidad infantil y gasto en salud por país", logy = TRUE)
Gráfico 7. Mortalidad infantil y gasto en salud por país
Fuente: WDI, Banco Mundial | 2019

La correlación es de solo -0,39: hay países con gasto parecido y mortalidades infantiles muy distintas. El gasto como porcentaje del PIB no basta para explicar los resultados, porque importan también el nivel de ingreso, la eficiencia del sistema y la cobertura de servicios básicos. Esta relación débil explica por qué el gasto en salud quedará mal representado en los primeros componentes.

Con un r² de solo 15 %, el gasto explica una fracción mínima de las diferencias en mortalidad infantil. La lectura de fondo es que lo decisivo no es cuánto se gasta sino en qué y con qué cobertura: vacunación, atención del parto, agua y saneamiento suelen pesar más que el monto total.

Envejecimiento y tasa bruta de mortalidad

La tasa bruta de mortalidad no mide solo salud, sino también la edad de la población. Este gráfico pone esa idea a prueba.

disp("Pob_65mas", "Tasa_Mortalidad", "Tasa bruta de mortalidad y envejecimiento por país")
Gráfico 8. Tasa bruta de mortalidad y envejecimiento por país
Fuente: WDI, Banco Mundial | 2019

A diferencia de las otras mortalidades, la tasa bruta aumenta con el envejecimiento (correlación de 0,44): los países más envejecidos tienen tasas altas aunque su salud sea buena, y varios países jóvenes tienen tasas muy bajas. Este comportamiento diferenciado anticipa que la tasa bruta definirá un segundo componente separado del primero.

La razón es demográfica: la tasa bruta divide las muertes entre toda la población, y una población envejecida tiene más personas en edades de mayor riesgo. Un país puede reducir su mortalidad en cada edad y aun así ver subir su tasa bruta porque envejece, un efecto conocido como paradoja de la mortalidad bruta.

Vista 3D

Tres de los indicadores más representativos, la fecundidad, la mortalidad infantil y la esperanza de vida, pueden verse a la vez en un gráfico tridimensional que se puede girar y ampliar.

plot_ly(paises, x = ~Fecundidad, y = ~Mort_Infantil, z = ~Esperanza_Vida, color = ~income,
        colors = pal_ingreso, type = "scatter3d", mode = "markers", text = ~country_name, height = 640,
        marker = list(size = 4, opacity = 0.85),
        hovertemplate = "<b>%{text}</b><br>Fecundidad: %{x:.1f}<br>Mort. infantil: %{y:.1f}<br>Esperanza de vida: %{z:.1f}<extra></extra>") %>%
  con_tit(tit_g("Fecundidad, mortalidad infantil y esperanza de vida")) %>%
  layout(font = fuente_plotly,
         scene = list(xaxis = list(title = "Fecundidad (hijos por mujer)"),
                      yaxis = list(title = "Mortalidad infantil (por 1.000)"),
                      zaxis = list(title = "Esperanza de vida (años)")),
         legend = leyenda_b("Nivel de ingreso"),
         margin = list(t = 30, b = 60, l = 10, r = 10), paper_bgcolor = "rgba(0,0,0,0)") %>%
  cfg()
Gráfico 9. Fecundidad, mortalidad infantil y esperanza de vida
Fuente: WDI, Banco Mundial | 2019

Los países forman una curva continua y no nubes separadas: desde el extremo de alta fecundidad, alta mortalidad infantil y baja esperanza de vida hasta el extremo opuesto. Esa continuidad es un hallazgo importante, porque indica que los grupos que se formen más adelante serán cortes de un gradiente y no categorías con fronteras nítidas.

Descripción de las variables categóricas

Las tres variables de apoyo se describen igual que las cuantitativas: primero su distribución en la muestra y luego su relación con los indicadores.

barra_cat <- function(var, titulo, pal = NULL, ordenar = FALSE) {
  d <- paises %>%
    count(across(all_of(var))) %>%
    setNames(c("cat", "n")) %>%
    mutate(cat = as.character(cat), pct = 100 * n / sum(n))
  if (ordenar) d <- arrange(d, n)
  d$cat <- factor(d$cat, levels = d$cat)
  cols <- if (is.null(pal)) "#52b788" else unname(pal[as.character(d$cat)])
  plot_ly(d, x = ~n, y = ~cat, type = "bar", orientation = "h", height = 360,
          text = ~paste0(n, " (", round(pct, 1), " %)"), textposition = "outside", cliponaxis = FALSE,
          marker = list(color = cols),
          hovertemplate = "%{y}<br>Países: %{x}<extra></extra>") %>%
    estilo("Número de países", "",
           tit_p(titulo),
           l = 210, b = 75, t = 60,
           xextra = list(range = c(0, max(d$n) * 1.3)),
           yextra = list(autorange = if (ordenar) TRUE else "reversed"))
}

tab_meta <- paises %>%
  count(income, Meta_ODS) %>%
  group_by(income) %>%
  mutate(pct = 100 * n / sum(n)) %>%
  ungroup()

Distribución de las categorías

Los tres paneles muestran cuántos países hay en cada categoría de región, nivel de ingreso y cumplimiento de la meta ODS.

grid_g(list(barra_cat("region", "Región", ordenar = TRUE),
            barra_cat("income", "Nivel de ingreso", pal_ingreso),
            barra_cat("Meta_ODS", "Meta ODS 3.2 (menores de 5 años)", pal_meta)),
       "Distribución de los países según las variables categóricas de apoyo")
Gráfico 10. Distribución de los países según las variables categóricas de apoyo
Fuente: WDI, Banco Mundial | 2019

La región con más países en la muestra es Europa y Asia Central (46 países) y el nivel de ingreso más frecuente es el medio-alto. El 64 % de los países ya cumple la meta ODS 3.2, y el 36 % restante está por encima del umbral de 25 muertes por 1.000 nacidos vivos. Las categorías no están perfectamente equilibradas, lo que hay que tener presente al comparar porcentajes entre grupos.

Meta ODS según ingreso

Esta pestaña cruza el cumplimiento de la meta con el nivel de ingreso, para ver si la meta se alcanza de forma pareja en todos los niveles.

plot_ly(tab_meta, x = ~income, y = ~pct, color = ~Meta_ODS, colors = pal_meta, type = "bar",
        text = ~paste0(n, " países"), height = 500,
        hovertemplate = "Ingreso %{x}<br>%{fullData.name}: %{y:.1f} % (%{text})<extra></extra>") %>%
  estilo("Nivel de ingreso", "Porcentaje de países del grupo",
         tit_g("Cumplimiento de la meta ODS 3.2 según el nivel de ingreso"), l = 90, b = 90,
         yextra = list(range = c(0, 100))) %>%
  layout(barmode = "stack", legend = leyenda_h("Meta ODS 3.2"))
Gráfico 11. Cumplimiento de la meta ODS 3.2 según el nivel de ingreso
Fuente: WDI, Banco Mundial | 2019

El cumplimiento de la meta pasa de 5 % en los países de ingreso bajo a 100 % en los de ingreso alto. Que algunos países de ingreso bajo o medio-bajo la cumplan, o que alguno de ingreso alto no lo haga, muestra que el ingreso condiciona pero no determina los resultados en salud infantil.

Región e ingreso

Esta tabla cruza las dos clasificaciones del Banco Mundial para ver qué tan homogénea es cada región en nivel de ingreso.

ri <- as.data.frame.matrix(table(paises$region, paises$income)) %>%
  rownames_to_column("Región")

tabla_t("Número de países por región y nivel de ingreso", dt(ri, n = 8, dom = "t", scrollX = TRUE))
Tabla 8. Número de países por región y nivel de ingreso
Fuente: elaboración propia con base en los WDI, 2019.

Una región concentrada en una sola columna es homogénea en ingreso; una repartida en varias combina niveles de desarrollo económico distintos. Región e ingreso están relacionados pero no son equivalentes, por lo que cada una aporta una referencia distinta para validar los grupos.

Matriz de correlaciones

La matriz de correlaciones es el insumo del ACP: si las variables no estuvieran correlacionadas, no habría nada que resumir. Se presenta como mapa de calor y como lista de los pares más correlacionados.

Mapa de calor

Las variables están ordenadas por similitud, de modo que las más relacionadas quedan juntas. El verde oscuro indica correlación positiva fuerte, el marrón correlación negativa fuerte y el blanco ausencia de relación.

ord <- hclust(as.dist(1 - matriz_cor))$order
mc <- matriz_cor[ord, ord]
nom_ord <- unname(etq_corta[rownames(mc)])

plot_ly(x = nom_ord, y = nom_ord, z = mc, type = "heatmap", height = 820,
        colorscale = esc_div, zmin = -1, zmax = 1,
        text = round(mc, 2), texttemplate = "%{text}", textfont = list(size = 10),
        hovertemplate = "%{y}<br>%{x}<br>r = %{z:.2f}<extra></extra>",
        colorbar = list(title = "r", len = 0.7, thickness = 14)) %>%
  estilo("", "", tit_g("Matriz de correlaciones entre los indicadores"),
         l = 150, b = 90,
         xextra = list(tickangle = -45, showgrid = FALSE, side = "bottom"),
         yextra = list(autorange = "reversed", showgrid = FALSE))
Gráfico 12. Matriz de correlaciones entre los indicadores
Fuente: WDI, Banco Mundial | 2019

Se distinguen dos grandes bloques de signo opuesto. Uno reúne las mortalidades, la natalidad, la fecundidad, la población joven, la desnutrición y las muertes transmisibles; el otro, la esperanza de vida, la vacunación, el envejecimiento y las muertes no transmisibles. Entre ambos bloques las correlaciones son negativas y fuertes. Hay 41 pares con |r| mayor que 0,8 de los 105 posibles, lo que confirma que los indicadores comparten buena parte de su información y justifica aplicar ACP. La tasa bruta de mortalidad y el gasto en salud quedan más sueltos, con correlaciones moderadas con casi todo, lo que anticipa que se representarán peor en el primer componente.

Una correlación mayor que 0,8 equivale a un r² superior al 64 %: más de dos tercios de la variación de una variable puede predecirse a partir de la otra. Con tantos pares en ese rango, mantener los 15 indicadores equivale a medir varias veces lo mismo, y es esa redundancia la que el ACP aprovecha para resumir sin perder casi nada.

Pares más correlacionados

La lista ordena todos los pares de variables por la magnitud de su correlación.

tabla_t(
  "Pares de variables ordenados por la magnitud de su correlación",
  dt(transmute(pares, `Variable A` = Variable_A, `Variable B` = Variable_B,
               r = r, `|r|` = abs_r), n = 8) %>%
    fr(c("r", "|r|"), 2)
)
Tabla 9. Pares de variables ordenados por la magnitud de su correlación
Fuente: elaboración propia con base en los WDI, 2019.

La correlación más fuerte es entre muertes por enfermedades transmisibles y muertes por enfermedades no transmisibles (r = -0,98); en parte es mecánica, porque ambas son proporciones del mismo total de muertes. Entre las demás destacan las mortalidades de menores de 5 años e infantil, que miden casi lo mismo, y la relación inversa de la esperanza de vida con las mortalidades. Estas redundancias son justamente las que el ACP concentra en pocos componentes.

Resultados del modelo

Análisis de Componentes Principales

El ACP se aplicó sobre las 15 variables estandarizadas de los 162 países. Esta sección presenta cuántos componentes se retienen, qué variables los definen, cómo se les nombra y cómo quedan ubicados los países en ellos.

pca <- PCA(X, scale.unit = TRUE, ncp = ncol(X), graph = FALSE)
eig <- as.data.frame(get_eigenvalue(pca))
ncp <- sum(eig$eigenvalue > 1)

signos <- rep(1, ncp)
signos[1] <- sign(pca$var$cor["Esperanza_Vida", 1])
if (ncp >= 2) signos[2] <- sign(pca$var$cor["Tasa_Mortalidad", 2])

cor_var <- sweep(pca$var$cor[, 1:ncp, drop = FALSE], 2, signos, "*")
colnames(cor_var) <- paste0("CP", 1:ncp)

S <- sweep(pca$ind$coord[, 1:ncp, drop = FALSE], 2, signos, "*")
colnames(S) <- paste0("Dim", 1:ncp)

coords <- as.data.frame(S)
coords$Dim3 <- pca$ind$coord[, 3]
coords$pais <- paises$country_name
coords$income <- paises$income

nombres_cp <- c("Desarrollo sanitario y demográfico", "Mortalidad bruta y envejecimiento")
eje <- function(i) paste0("CP", i, ": ", nombres_cp[i], " (", f1(eig$variance.percent[i]), " %)")

kais <- 100 / ncol(X)

lineas_cero <- list(
  list(type = "line", x0 = 0, x1 = 0, y0 = 0, y1 = 1, yref = "paper",
       line = list(color = "#9aa89f", dash = "dot")),
  list(type = "line", y0 = 0, y1 = 0, x0 = 0, x1 = 1, xref = "paper",
       line = list(color = "#9aa89f", dash = "dot"))
)

Varianza explicada y número de componentes

El primer paso es decidir cuántos componentes conservar. Se usan tres evidencias: los valores propios con el criterio de Kaiser (se retienen los mayores que 1), el gráfico de sedimentación y la varianza acumulada.

Valores propios

La tabla da, para cada componente, la varianza que explica y la decisión según el criterio de Kaiser.

tab_eig <- tibble(Componente = paste0("CP", seq_len(nrow(eig))),
                  `Valor propio` = eig$eigenvalue,
                  `% de varianza` = eig$variance.percent,
                  `% acumulado` = eig$cumulative.variance.percent,
                  Decisión = if_else(eig$eigenvalue > 1, "Se retiene", "Se descarta"))

tabla_t(
  "Valores propios y varianza explicada por componente principal",
  dt(tab_eig, n = 6) %>% fr(c("Valor propio", "% de varianza", "% acumulado"), 2)
)
Tabla 10. Valores propios y varianza explicada por componente principal
Fuente: elaboración propia con base en los WDI, 2019.

Se retienen 2 componentes. El primero explica el 70,6 % de la variabilidad, un porcentaje muy alto que indica que la mayor parte de los 15 indicadores responde a un mismo proceso de fondo. El segundo aporta el 12,0 %, y juntos suman 82,5 %. El tercer componente tiene un valor propio de 0,72, inferior a 1, y solo explica el 4,8 %, por lo que se descarta.

Detrás del 70,6 % hay una idea simple: conocer la posición de un país en un único eje permite reconstruir cerca de 7 de cada 10 unidades de la variabilidad que existe entre países en los 15 indicadores. Los 15 indicadores no son 15 fenómenos independientes sino manifestaciones de uno o dos procesos de fondo, y eso tiene una consecuencia práctica: mejorar un indicador, como la mortalidad infantil, rara vez ocurre de forma aislada, porque se mueve junto con la fecundidad, la longevidad y el perfil de enfermedades. El 17,5 % que queda sin explicar es información específica de cada indicador, o ruido de medición, que se sacrifica a cambio de simplicidad.

¿Qué significa un valor propio? Como cada variable estandarizada aporta exactamente una unidad de varianza, el valor propio dice a cuántas variables originales «equivale» un componente. El primero vale 10,59: resume tanta información como 10,6 de los 15 indicadores juntos. El segundo vale 1,79, algo más que un indicador completo. El tercero vale 0,72, menos que una sola variable: conservarlo sería como añadir al análisis una fracción de indicador, y por eso el criterio de Kaiser lo descarta.

Gráfico de sedimentación

El gráfico muestra el porcentaje de varianza de cada componente, con una línea que une la altura de las barras y una línea punteada con el criterio de Kaiser.

sc <- tibble(comp = paste0("CP", 1:8), pct = eig$variance.percent[1:8]) %>%
  mutate(comp = factor(comp, levels = comp))

plot_ly(sc, x = ~comp, height = 520) %>%
  add_bars(y = ~pct, name = "Varianza explicada", marker = list(color = "#52b788"),
           text = ~paste0(round(pct, 1), " %"), textposition = "outside", cliponaxis = FALSE,
           hovertemplate = "%{x}<br>%{y:.1f} % de la varianza<extra></extra>") %>%
  add_trace(y = ~pct, type = "scatter", mode = "lines+markers", name = "Perfil de sedimentación",
            line = list(color = "#0b522c", width = 2.5), marker = list(color = "#0b522c", size = 9),
            hoverinfo = "skip") %>%
  add_trace(y = rep(kais, nrow(sc)), type = "scatter", mode = "lines", name = "Criterio de Kaiser (λ = 1)",
            line = list(color = "#c7a64a", dash = "dash", width = 2),
            hovertemplate = "Varianza de una variable original: %{y:.2f} %<extra></extra>") %>%
  estilo("Componente principal", "Varianza explicada (%)", tit_g("Gráfico de sedimentación del ACP"),
         l = 90, b = 90, yextra = list(range = c(0, max(sc$pct) * 1.15))) %>%
  layout(legend = leyenda_h("Series"))
Gráfico 13. Gráfico de sedimentación del ACP
Fuente: WDI, Banco Mundial | 2019

La línea cae de forma abrupta entre el primer y el segundo componente y se aplana desde el tercero: ese “codo” indica que a partir de ahí los componentes aportan poco. La línea dorada equivale a 6,67 %, la varianza que aporta una sola variable original; solo los dos primeros componentes la superan, lo que coincide con el criterio de Kaiser. Las tres evidencias coinciden en retener 2 componentes con una varianza acumulada de 82,5 %, suficiente para resumir los 15 indicadores con poca pérdida de información.

El codo tiene también una lectura sustantiva: a partir del segundo componente, agregar una dimensión no revela estructura nueva sino diferencias menores entre países, que no justifican la complejidad adicional.

Relación de las variables con los componentes

Una vez fijado el número de componentes hay que entender qué significan. Para eso se examina cuánto correlaciona cada variable con cada componente, cuánto contribuye a definirlo y cómo se ubica en el círculo de correlaciones.

Correlaciones y calidad

La tabla da la correlación de cada variable con los componentes y la calidad de su representación, es decir, el porcentaje de su varianza que reproducen los componentes retenidos.

tab_cor <- bind_cols(
  tibble(var = rownames(cor_var),
         Dimensión = dim_tab$Dimension[match(rownames(cor_var), dim_tab$var)],
         Variable = unname(etiquetas[rownames(cor_var)])),
  as_tibble(cor_var),
  tibble(`Calidad de representación (%)` = rowSums(cor_var^2) * 100)
) %>%
  arrange(match(var, unlist(dimensiones))) %>%
  select(-var)

tabla_t(
  "Correlación de cada variable con los componentes y calidad de su representación",
  dt(tab_cor, n = 15, scrollX = TRUE) %>%
    fr(c(paste0("CP", 1:ncp), "Calidad de representación (%)"), 2) %>%
    formatStyle(paste0("CP", 1:ncp),
                backgroundColor = styleInterval(c(-0.7, 0.7), c("#f3e7c3", "transparent", "#cfe8d8")))
)
Tabla 11. Correlación de cada variable con los componentes y calidad de su representación
Fuente: elaboración propia con base en los WDI, 2019.

Las celdas verdes marcan correlaciones fuertes positivas (mayores que 0,7) y las doradas, fuertes negativas. En CP1 superan ese umbral 12 de las 15 variables: 3 en positivo (la esperanza de vida, las muertes no transmisibles y la población de 65 años o más) y 9 en negativo (las cuatro mortalidades, la natalidad, la fecundidad, la población de 0 a 14 años, la desnutrición y las muertes transmisibles). Las tres restantes no lo alcanzan: la vacunación DPT (0,65), el gasto en salud (0,50) y la tasa bruta de mortalidad (-0,10), que casi no se relaciona con este componente. CP2 es distinto: solo la tasa bruta de mortalidad lo supera (0,96), con valores moderados para la población de 65 años o más (0,52) y el gasto en salud (0,44). Por eso CP1 se lee como un eje de desarrollo, en el que a mayor valor hay más longevidad y menos mortalidad, y CP2 recoge casi por sí solo la tasa bruta.

En la calidad de representación, 12 de las 15 variables superan el 80 %. Las tres peor representadas son gasto corriente en salud, vacunación DPT y prevalencia de desnutrición (44 %, 47 % y 59 %), porque parte de su información quedó en los componentes que se descartaron.

Contribuciones

Las barras muestran qué porcentaje de la varianza de cada componente aporta cada variable. La línea dorada marca la contribución promedio, es decir, lo que aportaría cada variable si todas pesaran igual.

contrib_cp <- function(i) {
  d <- tibble(var = unname(etiquetas[rownames(pca$var$contrib)]), ctr = pca$var$contrib[, i]) %>%
    arrange(ctr) %>%
    mutate(var = factor(var, levels = var))
  plot_ly(d, x = ~ctr, y = ~var, type = "bar", orientation = "h", height = 480,
          marker = list(color = ifelse(d$ctr > kais, "#0b522c", "#9fd3b8")),
          hovertemplate = "%{y}<br>Contribución: %{x:.1f} %<extra></extra>") %>%
    estilo("Contribución a la varianza del componente (%)", "",
           tit_p(eje(i)),
           l = 280, b = 85, t = 70) %>%
    layout(shapes = list(list(type = "line", x0 = kais, x1 = kais, y0 = 0, y1 = 1,
                              yref = "paper", line = list(color = "#c7a64a", dash = "dash", width = 2))))
}

grid_g(lapply(seq_len(ncp), contrib_cp), "Contribución de las variables a cada componente", cols = 1)
Gráfico 14. Contribución de las variables a cada componente
Fuente: WDI, Banco Mundial | 2019

Las barras verde oscuro superan la contribución promedio (6,67 %) y son las que definen el componente. El primer componente está construido de forma pareja por muchas variables: las mortalidades, la natalidad, la fecundidad, la esperanza de vida y el perfil epidemiológico aportan cada una entre el 7 % y el 9 % de su varianza, lo que indica que es un componente genuinamente general. El segundo es lo contrario: está dominado por la tasa bruta de mortalidad, con aportes menores de la población de 65 años o más y del gasto en salud, de modo que es un componente específico de ese fenómeno.

Que el primer componente sea general significa que ningún indicador lo monopoliza: si se quitara uno, el eje casi no cambiaría. Esa robustez permite interpretarlo como un fenómeno de fondo, la transición, y no como el reflejo de una sola variable.

Círculo de correlaciones

El círculo ubica cada variable según su correlación con el primer componente (eje horizontal) y el segundo (eje vertical). Los puntos están coloreados por dimensión y al pasar el cursor se ve el nombre de la variable.

cv <- tibble(x = cor_var[, 1], y = cor_var[, 2],
             var = unname(etiquetas[rownames(cor_var)]),
             dimension = dim_tab$Dimension[match(rownames(cor_var), dim_tab$var)])

plot_ly(height = 700) %>%
  add_segments(data = cv, x = 0, y = 0, xend = ~x, yend = ~y,
               line = list(color = "#9aa89f", width = 1.4), hoverinfo = "none", showlegend = FALSE) %>%
  add_markers(data = cv, x = ~x, y = ~y, color = ~dimension, colors = pal_dim, text = ~var,
              marker = list(size = 13, line = list(color = "white", width = 1)),
              hovertemplate = "<b>%{text}</b><br>CP1: %{x:.2f}<br>CP2: %{y:.2f}<extra></extra>") %>%
  estilo(eje(1), eje(2), tit_g("Círculo de correlaciones de las variables con CP1 y CP2"),
         l = 90, b = 90, r = 270,
         xextra = list(range = c(-1.2, 1.2), zeroline = TRUE, zerolinecolor = "#9aa89f", scaleanchor = "y"),
         yextra = list(range = c(-1.2, 1.2), zeroline = TRUE, zerolinecolor = "#9aa89f")) %>%
  layout(shapes = list(list(type = "circle", xref = "x", yref = "y", x0 = -1, y0 = -1, x1 = 1, y1 = 1,
                            line = list(color = "#9aa89f", dash = "dot"))),
         legend = leyenda_v("Dimensión"))
Gráfico 15. Círculo de correlaciones de las variables con CP1 y CP2
Fuente: WDI, Banco Mundial | 2019

Mientras más cerca del círculo punteado está una variable, mejor representada queda en el plano; mientras más lejos del centro, más fuerte es su relación con los ejes. A la derecha se agrupan la esperanza de vida, las muertes no transmisibles, la vacunación y el envejecimiento, y a la izquierda las mortalidades, la natalidad, la fecundidad, la población joven, la desnutrición y las muertes transmisibles: dos bloques opuestos sobre el primer eje. En vertical se separa la tasa bruta de mortalidad, casi sola, lo que confirma que describe algo distinto. El gasto en salud y la vacunación quedan más cerca del centro, es decir, peor representados en este plano.

El ángulo entre dos flechas se lee como correlación: flechas casi paralelas indican variables casi equivalentes, como la mortalidad infantil y la de menores de 5 años, y flechas casi perpendiculares indican variables sin relación, como la tasa bruta de mortalidad frente al eje de desarrollo.

Interpretación y nombre de los componentes

Siguiendo la práctica habitual, los componentes se nombran a partir de las variables que los definen, para poder usar esos nombres al interpretar los grupos.

nom_cp <- tibble(
  Componente = paste0("CP", 1:ncp),
  `Varianza explicada` = paste0(f1(eig$variance.percent[1:ncp]), " %"),
  `Variables que lo definen` = c(
    "Polo positivo: esperanza de vida, muertes no transmisibles, vacunación y envejecimiento. Polo negativo: mortalidad infantil y adulta, natalidad, fecundidad, población joven, desnutrición y muertes transmisibles",
    "Polo positivo: tasa bruta de mortalidad, población de 65 años o más y gasto en salud. Polo negativo: población joven y natalidad"
  ),
  Interpretación = c(
    "Posición del país en la transición demográfica y epidemiológica: de mortalidad y natalidad altas con enfermedades transmisibles, a longevidad, baja natalidad y enfermedades crónicas",
    "Mortalidad general asociada al envejecimiento: separa a países envejecidos con tasa bruta alta de países jóvenes con tasa bruta baja, independientemente de su nivel de salud"
  ),
  `Nombre asignado` = nombres_cp[1:ncp]
)

tabla_t("Componentes principales retenidos, interpretación y nombre asignado",
        dt(nom_cp, n = 4, dom = "t", envolver = TRUE))
Tabla 12. Componentes principales retenidos, interpretación y nombre asignado
Fuente: elaboración propia con base en los WDI, 2019.

El primer componente, Desarrollo sanitario y demográfico, ordena a los países desde los de mayor mortalidad, natalidad y carga de enfermedades transmisibles hasta los de mayor longevidad y predominio de enfermedades crónicas. Un valor alto indica un país en una etapa avanzada de la transición. Que por sí solo explique el 70,6 % de la variabilidad significa que la salud y la demografía de un país no son procesos independientes: avanzan juntos.

El segundo componente, Mortalidad bruta y envejecimiento, recoge algo que el primero no ve. La tasa bruta de mortalidad depende de la edad de la población, así que un país envejecido muestra una tasa alta aunque su salud sea buena, y un país muy joven una tasa baja aunque su salud sea precaria. Un valor alto indica una mortalidad bruta elevada con población envejecida, y un valor bajo, una población joven con mortalidad bruta baja. La tasa bruta de mortalidad es, por tanto, una variable poco confiable para comparar la salud de países con estructuras de edad distintas.

Este resultado es coherente con la teoría. Las transiciones demográfica y epidemiológica no son procesos separados: cuando un país mejora la nutrición, el saneamiento y la atención materno-infantil, cae primero la mortalidad infantil, después la natalidad, y más tarde la población envejece y las enfermedades crónicas pasan a ser la principal causa de muerte. El primer componente es la huella estadística de esa secuencia, y el segundo, la del envejecimiento con el que se cierra el ciclo.

Países en el plano factorial

El plano de los dos componentes permite ver a cada país en el espacio donde se hará la clusterización. Se muestra por nivel de ingreso para contrastar el eje de desarrollo con una clasificación económica conocida.

plot_ly(coords, x = ~Dim1, y = ~Dim2, color = ~income, colors = pal_ingreso,
        type = "scatter", mode = "markers", text = ~pais, height = 620,
        marker = list(size = 9, opacity = 0.85, line = list(color = "white", width = 0.8)),
        hovertemplate = "<b>%{text}</b><br>CP1: %{x:.2f}<br>CP2: %{y:.2f}<extra></extra>") %>%
  estilo(eje(1), eje(2), tit_g("Países en el plano de CP1 y CP2 según nivel de ingreso"),
         l = 90, b = 90) %>%
  layout(shapes = lineas_cero, legend = leyenda_h("Nivel de ingreso"))
Gráfico 16. Países en el plano de CP1 y CP2 según nivel de ingreso
Fuente: WDI, Banco Mundial | 2019
rk1 <- coords %>% arrange(desc(Dim1))
rk2 <- coords %>% arrange(desc(Dim2))

De izquierda a derecha aumenta el desarrollo sanitario y demográfico: en el extremo derecho están Japón, Italia, Suiza, España, Finlandia, y en el izquierdo República Democrática del Congo, Nigeria, Somalia, Chad, República Centroafricana. De abajo hacia arriba aumenta la mortalidad bruta asociada al envejecimiento: arriba se ubican República Centroafricana, Bulgaria, Serbia, Letonia, y abajo Arabia Saudí, Kuwait, Omán, Emiratos Árabes Unidos, países con poblaciones muy jóvenes y tasa bruta baja. Los colores se ordenan sobre el eje horizontal, pero los niveles de ingreso intermedios se traslapan, lo que muestra que el ingreso explica solo en parte la posición de un país.

Para la política pública esto tiene una consecuencia: si el ingreso no ordena perfectamente el eje, hay margen para mejorar la salud sin esperar a enriquecerse. Los países de ingreso medio con mejor posición que otros de ingreso similar muestran que la cobertura de servicios básicos, la educación y las decisiones de política pesan además del ingreso.

Clusterización jerárquica de Ward

La clusterización se hizo sobre las coordenadas de los países en los 2 componentes retenidos. Primero se decide cuántos grupos formar y luego se caracteriza cada uno.

k_opt <- 3

hc <- hclust(dist(S), method = "ward.D2")
alt <- tibble(k = 2:10, altura = rev(hc$height)[1:9])
sil <- tibble(k = 2:10, silueta = sapply(2:10, function(k) mean(silhouette(cutree(hc, k), dist(S))[, 3])))

cl <- cutree(hc, k_opt)
orden <- order(tapply(paises$Esperanza_Vida, cl, mean))
nombres_cl <- if (k_opt == 3) c("Transición temprana", "Transición intermedia", "Transición avanzada") else paste("Grupo", seq_len(k_opt))
paises$cluster <- factor(match(cl, orden), levels = seq_len(k_opt),
                         labels = paste0(seq_len(k_opt), ". ", nombres_cl))
coords$cluster <- paises$cluster
pal_cl <- setNames(pal_cluster[seq_len(k_opt)], levels(paises$cluster))

perfil_w <- paises %>%
  group_by(cluster) %>%
  summarise(n = n(), across(all_of(names(vars)), mean))
g <- perfil_w

tam4 <- table(cutree(hc, 4))
pais_aislado <- paises$country_name[cutree(hc, 4) %in% names(tam4)[tam4 == 1]]

tam_txt <- function(x) paste(sort(as.vector(table(x)), decreasing = TRUE), collapse = " / ")
max_pct <- function(x) 100 * max(table(x)) / length(x)
g_raw <- cutree(hclust(dist(X), method = "ward.D2"), k_opt)
g_std <- cutree(hclust(dist(scale(X)), method = "ward.D2"), k_opt)

linea_k <- list(list(type = "line", x0 = k_opt, x1 = k_opt, y0 = 0, y1 = 1, yref = "paper",
                     line = list(color = "#c7a64a", dash = "dash", width = 2)))

Número de grupos

Se evaluaron cuatro criterios: la altura de fusión, el índice de silueta, el tamaño de los grupos y el efecto de la estandarización. Cada pestaña muestra uno de ellos.

Altura de fusión y silueta

El panel izquierdo da la altura a la que se produce la fusión que reduce la jerarquía de \(k\) a \(k-1\) grupos; el derecho, la silueta media para cada número de grupos. La línea dorada marca la solución elegida.

p_alt <- plot_ly(alt, x = ~k, y = ~altura, type = "scatter", mode = "lines+markers", height = 400,
                 line = list(color = "#0b522c", width = 2.5), marker = list(color = "#0b522c", size = 9),
                 hovertemplate = "%{x} grupos<br>Altura de fusión: %{y:.1f}<extra></extra>") %>%
  estilo("Número de grupos antes de la fusión", "Altura de la fusión",
         tit_p("Altura de fusión"),
         l = 80, b = 80, t = 60, xextra = list(dtick = 1)) %>%
  layout(shapes = linea_k)

p_sil <- plot_ly(sil, x = ~k, y = ~silueta, type = "scatter", mode = "lines+markers", height = 400,
                 line = list(color = "#0b522c", width = 2.5), marker = list(color = "#0b522c", size = 9),
                 hovertemplate = "%{x} grupos<br>Silueta media: %{y:.3f}<extra></extra>") %>%
  estilo("Número de grupos", "Silueta media",
         tit_p("Índice de silueta"),
         l = 80, b = 80, t = 60, xextra = list(dtick = 1)) %>%
  layout(shapes = linea_k)

grid_g(list(p_alt, p_sil), "Criterios para elegir el número de grupos")
Gráfico 17. Criterios para elegir el número de grupos
Fuente: WDI, Banco Mundial | 2019

Las fusiones más costosas ocurren al pasar de 2 a 1 grupos (49,8) y de 3 a 2 (25,0), y el costo disminuye de forma gradual desde 5 grupos: hasta 3 o 4 grupos se están separando perfiles realmente distintos. En la silueta, las soluciones de 2, 3 y 4 grupos obtienen 0,58, 0,52 y 0,53, todas por encima de 0,5, que indica una estructura razonable. Como la diferencia entre 3 y 4 grupos es pequeña, la decisión se apoya en los otros criterios.

Una silueta de 0,5 a 0,6 significa que, en promedio, un país está claramente más cerca de los de su grupo que de los del grupo vecino, pero no tan separado como en una estructura muy marcada. Esto concuerda con lo visto antes: los países se distribuyen a lo largo de un gradiente continuo, así que los grupos son cortes útiles de ese gradiente y no categorías con fronteras nítidas.

Tamaño de los grupos

La tabla da, para cada número de grupos, la silueta media, el tamaño de los grupos de mayor a menor y cuántos tienen un solo país.

tam_k <- tibble(
  `Número de grupos` = 2:6,
  `Silueta media` = sil$silueta[match(2:6, sil$k)],
  `Tamaño de los grupos` = sapply(2:6, function(k) tam_txt(cutree(hc, k))),
  `Grupos de un solo país` = sapply(2:6, function(k) sum(table(cutree(hc, k)) == 1))
)

tabla_t("Silueta y tamaño de los grupos según el número de grupos elegido",
        dt(tam_k, n = 5, dom = "t") %>% fr("Silueta media", 3))
Tabla 13. Silueta y tamaño de los grupos según el número de grupos elegido
Fuente: elaboración propia con base en los WDI, 2019.

Con 2 grupos la silueta es la más alta, pero esa solución solo separa a los países de peor salud del resto y no distingue etapas intermedias. Con 4 grupos aparece un grupo formado por un solo país, República Centroafricana, un caso atípico con valores extremos en casi todas las variables, que no describe un perfil compartido sino una excepción. Con 3 grupos los tamaños son 66 / 52 / 44: ninguno es marginal y los tres son interpretables. Por eso se eligió k = 3.

Efecto de la estandarización

Esta pestaña compara los tamaños de los 3 grupos que se obtienen con Ward sobre los datos originales, sobre las variables estandarizadas y sobre la solución final con ACP.

cmp <- tibble(
  Solución = c("Sin estandarizar (15 variables originales)",
               "Estandarizadas (15 variables en puntaje z)",
               "Final: ACP sobre variables estandarizadas"),
  `Tamaño de los grupos` = c(tam_txt(g_raw), tam_txt(g_std), tam_txt(cl)),
  `Grupo más grande (%)` = c(max_pct(g_raw), max_pct(g_std), max_pct(cl))
)

tabla_t("Tamaño de los grupos según el tratamiento de las variables",
        dt(cmp, n = 3, dom = "t") %>% fr("Grupo más grande (%)", 1))
Tabla 14. Tamaño de los grupos según el tratamiento de las variables
Fuente: elaboración propia con base en los WDI, 2019.

Sin estandarizar, la clusterización queda determinada por las variables de mortalidad adulta, que concentran la mayor parte de la varianza, y no por el conjunto de indicadores. Con la estandarización todas las variables pesan igual. En la solución final, el grupo más grande reúne el 40,7 % de los países y el más pequeño el 27,2 %: los tamaños no son idénticos, pero ninguno es marginal, lo cual es esperable porque Ward minimiza la varianza interna y no impone tamaños iguales. Los grupos desiguales no son un defecto del método sino un reflejo de que hay más países en unas etapas de la transición que en otras.

Silueta de cada país

La silueta media resume a todos los países en un solo número. Este gráfico la descompone: cada barra es un país, ordenado dentro de su grupo de mayor a menor silueta, y al pasar el cursor se ve el grupo al que más se parece después del suyo.

sil_obj <- silhouette(as.integer(paises$cluster), dist(S))
sil_df <- tibble(pais = paises$country_name, cluster = paises$cluster,
                 s = sil_obj[, 3], vecino = levels(paises$cluster)[sil_obj[, 2]]) %>%
  arrange(cluster, desc(s)) %>%
  mutate(pos = row_number())
sil_media <- sil_df %>% group_by(cluster) %>% summarise(s = mean(s), neg = sum(s < 0))
neg_sil <- sil_df %>% filter(s < 0) %>% arrange(s)

plot_ly(sil_df, x = ~s, y = ~pos, type = "bar", orientation = "h", color = ~cluster, colors = pal_cl,
        text = ~pais, customdata = ~vecino, textposition = "none", height = 560,
        hovertemplate = "<b>%{text}</b><br>Silueta: %{x:.2f}<br>Grupo vecino: %{customdata}<extra></extra>") %>%
  estilo("Silueta del país", "", tit_g("Silueta de cada país, ordenada dentro de su grupo"),
         l = 40, b = 80,
         xextra = list(zeroline = TRUE, zerolinecolor = "#1b4332", zerolinewidth = 1.5),
         yextra = list(showticklabels = FALSE, ticks = "", showgrid = FALSE, autorange = "reversed")) %>%
  layout(bargap = 0, legend = leyenda_h("Grupo"))
Gráfico 18. Silueta de cada país, ordenada dentro de su grupo
Fuente: WDI, Banco Mundial | 2019

¿Cómo se lee un valor? La silueta compara dos distancias: la distancia promedio del país a los de su propio grupo (\(a\)) y la distancia promedio al grupo vecino (\(b\)). Cuando \(a\) es menor que \(b\), la silueta vale \(1 - a/b\), así que un país con 0,60 está, en promedio, a solo el 40 % de la distancia a la que está del grupo vecino. Un valor de 0 significa que ambas distancias son iguales, y uno negativo, que el grupo vecino le queda más cerca que el propio.

La silueta media es de 0,53 en la transición temprana (grupo 1), 0,45 en la transición intermedia (grupo 2) y 0,61 en la transición avanzada (grupo 3). Dos países, Mauricio y Argentina, quedan a la izquierda del cero: en promedio están más cerca del grupo vecino que del propio. No están mal clasificados, sino en la frontera entre dos etapas de la transición, así que sus resultados deben leerse con más cautela que los del núcleo de cada grupo.

Dendrograma

Un dendrograma es un diagrama de árbol que muestra el orden en que el método de Ward fue uniendo a los países. En la base está cada país, como una hoja; hacia arriba, los países y grupos más parecidos se van juntando en ramas, hasta que todo queda reunido en una sola. La altura a la que se unen dos ramas mide cuánta homogeneidad se pierde con esa unión: las uniones bajas reúnen perfiles casi iguales y las altas, perfiles muy distintos. La línea punteada dorada marca la altura de corte que deja 3 grupos, cada uno con el mismo color que tiene en el resto del documento, y las uniones por encima del corte van en gris.

dd <- dendro_data(hc, type = "rectangle")
seg <- dd$segments
hcorte <- (rev(hc$height)[k_opt - 1] + rev(hc$height)[k_opt]) / 2
cl_hoja <- as.character(paises$cluster)[hc$order]
nn <- nrow(paises)

tss <- sum(scale(S, scale = FALSE)^2)
delta <- rev(hc$height)^2 / 2
pct_entre <- 100 * sum(delta[seq_len(k_opt - 1)]) / tss
pct_ult <- 100 * delta[1] / tss

seg$grupo <- ifelse(pmin(seg$y, seg$yend) < hcorte,
                    cl_hoja[pmin(pmax(round((seg$x + seg$xend) / 2), 1), nn)],
                    "Fusiones entre grupos")
hojas <- tibble(x = seq_len(nn), y = 0, pais = paises$country_name[hc$order], grupo = cl_hoja)

plot_ly(height = 660) %>%
  add_segments(data = seg, x = ~x, xend = ~xend, y = ~y, yend = ~yend, color = ~grupo,
               colors = c(pal_cl, "Fusiones entre grupos" = "#9aa89f"),
               line = list(width = 1.6), hoverinfo = "none") %>%
  add_markers(data = hojas, x = ~x, y = ~y, color = ~grupo, colors = pal_cl, text = ~pais,
              customdata = ~grupo, showlegend = FALSE,
              marker = list(size = 7, line = list(color = "white", width = 0.6)),
              hovertemplate = "<b>%{text}</b><br>%{customdata}<extra></extra>") %>%
  estilo("", "Altura de la fusión (distancia de Ward)",
         tit_g("Dendrograma del método de Ward"), l = 90, b = 70,
         xextra = list(showticklabels = FALSE, showgrid = FALSE, ticks = "",
                       zeroline = FALSE, range = c(-2, nn + 3)),
         yextra = list(rangemode = "tozero")) %>%
  layout(shapes = list(list(type = "line", x0 = 0, x1 = 1, xref = "paper", y0 = hcorte, y1 = hcorte,
                            line = list(color = "#c7a64a", dash = "dash", width = 2))),
         annotations = list(
           list(x = 1, xref = "paper", xanchor = "right", y = hcorte, yref = "y", yanchor = "bottom",
                text = paste0("<b>Corte en ", k_opt, " grupos</b> (altura ", f1(hcorte), ")"),
                showarrow = FALSE, font = list(size = 12, color = "#8a6d1f")),
           list(x = 0.5, xref = "paper", xanchor = "center", y = 0, yref = "paper", yanchor = "top",
                yshift = -10, showarrow = FALSE, font = list(size = 13, color = "#4a5d52"),
                text = paste0(nn, " países"))),
         legend = leyenda_h("Grupo"))
Gráfico 19. Dendrograma del método de Ward
Fuente: WDI, Banco Mundial | 2019

Al cortar el árbol a la altura de 21,5 se obtienen 3 ramas principales, que son los tres grupos. La unión de los dos grupos más cercanos ocurre a una altura de 25,0 y la del último par, a 49,8: el grupo de transición temprana es el más distinto del resto y queda separado hasta el final, mientras que los grupos intermedio y avanzado se parecen más entre sí. Las ramas dentro de cada grupo son cortas, lo que indica países con perfiles muy parecidos, y los países que se unen tarde a su grupo son los más atípicos.

¿Qué significa una altura? En el método de Ward, la altura de una unión mide cuánta homogeneidad se pierde al juntar dos grupos: una altura \(h\) equivale a un aumento de \(h^2/2\) en la suma de cuadrados dentro de los grupos. Traducido a porcentaje, la última unión, la de altura 49,8, mezclaría perfiles que hoy concentran el 61,9 % de toda la variabilidad del plano de los componentes. Los 3 grupos elegidos, en conjunto, dejan entre ellos el 77,4 % de esa variabilidad; el 22,6 % restante son las diferencias que todavía existen entre países de un mismo grupo. Es decir, saber a qué grupo pertenece un país ya explica 8 de cada 10 unidades de lo que lo diferencia de los demás.

Caracterización de los grupos

Con los grupos formados, la pregunta es qué los distingue. Se examinan sus promedios, su perfil frente al promedio global, su forma en las 15 variables y los indicadores que los caracterizan estadísticamente.

Promedios por grupo

La tabla da el promedio de las 15 variables en cada grupo y en el conjunto de países.

perfil_long <- paises %>%
  pivot_longer(all_of(names(vars)), names_to = "var", values_to = "valor") %>%
  group_by(cluster, var) %>%
  summarise(media = mean(valor), .groups = "drop")

perfil_t <- perfil_long %>%
  pivot_wider(names_from = cluster, values_from = media) %>%
  mutate(Global = unname(colMeans(X)[var])) %>%
  left_join(dim_tab, by = "var") %>%
  mutate(Variable = unname(etiquetas[var])) %>%
  arrange(match(var, unlist(dimensiones))) %>%
  select(Dimensión = Dimension, Variable, all_of(levels(paises$cluster)), `Promedio global` = Global)

tabla_t("Promedio de cada variable por grupo de países",
        dt(perfil_t, n = 15, scrollX = TRUE) %>%
          fr(c(levels(paises$cluster), "Promedio global"), 1))
Tabla 15. Promedio de cada variable por grupo de países
Fuente: elaboración propia con base en los WDI, 2019.

Los promedios muestran un gradiente ordenado: de un grupo al siguiente la esperanza de vida sube de 62,1 a 73,2 y a 79,6 años, y la mortalidad de menores de 5 años baja de 71 a 20 y a 5,2 por 1.000. La tasa bruta de mortalidad rompe ese orden: es de 8,5 en el primer grupo, baja a 6,0 en el intermedio y sube a 9,9 en el avanzado, por el envejecimiento.

En términos concretos, un niño que nace en un país del primer grupo tiene 14 veces más probabilidad de morir antes de los 5 años que uno que nace en un país del tercero (71 frente a 5,2 por 1.000), y vive en promedio 18 años menos. La fecundidad pasa de 4,4 a 1,5 hijos por mujer, por debajo del nivel de reemplazo (cerca de 2,1) en el grupo avanzado: son poblaciones que, sin migración, tienden a envejecer y a reducirse. La paradoja de la tasa bruta deja claro que mirar un solo indicador puede llevar a conclusiones equivocadas.

Perfil frente al promedio global

El mapa de calor muestra el promedio de cada variable en cada grupo (número dentro de la celda) y qué tan lejos está del promedio global, medido en desviaciones estándar (color).

orden_var <- unlist(dimensiones)
mu <- colMeans(X)
sdv <- apply(X, 2, sd)
niveles <- levels(paises$cluster)

mm <- sapply(niveles, function(gr) colMeans(X[paises$cluster == gr, orden_var, drop = FALSE]))
mz <- (mm - mu[orden_var]) / sdv[orden_var]

plot_ly(x = niveles, y = unname(etq_corta[orden_var]), z = mz, type = "heatmap", height = 700,
        colorscale = esc_div, zmin = -2, zmax = 2, text = round(mm, 1), texttemplate = "%{text}",
        textfont = list(size = 12),
        hovertemplate = "%{y}<br>%{x}<br>Promedio: %{text}<br>Distancia al promedio global: %{z:.2f} desv. est.<extra></extra>",
        colorbar = list(title = "Desv. est.", len = 0.7, thickness = 14)) %>%
  estilo("", "", tit_g("Perfil de cada grupo respecto al promedio global"),
         l = 150, b = 100,
         xextra = list(showgrid = FALSE),
         yextra = list(autorange = "reversed", showgrid = FALSE))
Gráfico 20. Perfil de cada grupo respecto al promedio global
Fuente: WDI, Banco Mundial | 2019

Cada grupo tiene una “huella” de colores distinta. El primer grupo concentra los tonos verdes en las mortalidades, la natalidad, la fecundidad, la población joven, la desnutrición y las muertes transmisibles, y los marrones en esperanza de vida, vacunación y envejecimiento. El tercero muestra el patrón inverso. El grupo intermedio se mantiene cerca del blanco en casi todas las variables, es decir, cerca del promedio global, lo que lo describe como una etapa de transición.

Forma de cada grupo

El gráfico radar dibuja, para cada grupo, la distancia al promedio global en las 15 variables a la vez, lo que permite comparar la forma de los perfiles.

rad <- plot_ly(type = "scatterpolar", mode = "lines", fill = "toself", height = 640)
for (gr in niveles) {
  rad <- rad %>% add_trace(r = c(mz[, gr], mz[1, gr]),
                           theta = c(unname(etq_corta[rownames(mz)]), unname(etq_corta[rownames(mz)[1]])),
                           name = gr, line = list(color = pal_cl[[gr]], width = 2.5),
                           fillcolor = adjustcolor(pal_cl[[gr]], alpha.f = 0.25),
                           hovertemplate = "%{theta}<br>%{r:.2f} desv. est.<extra></extra>")
}
rad %>%
  con_tit(tit_g("Forma del perfil de cada grupo en las 15 variables")) %>%
  layout(font = fuente_plotly,
         polar = list(radialaxis = list(range = c(-2, 2), tickfont = list(size = 10), gridcolor = "#d8e2dc"),
                      angularaxis = list(tickfont = list(size = 11))),
         legend = leyenda_b("Grupo"), margin = list(t = 70, b = 90, l = 80, r = 80),
         paper_bgcolor = "rgba(0,0,0,0)") %>%
  cfg()
Gráfico 21. Forma del perfil de cada grupo en las 15 variables
Fuente: WDI, Banco Mundial | 2019

Las formas son claramente distintas. El primer grupo se extiende hacia afuera en el lado de las mortalidades, la natalidad y la desnutrición, y se contrae en esperanza de vida y envejecimiento; el tercero hace lo contrario; y el intermedio forma un polígono pequeño y cercano al centro. Que los polígonos casi no se crucen indica que los grupos están ordenados a lo largo de un mismo gradiente y que la separación no depende de una sola variable.

Variables características

La tabla ordena, para cada grupo, las variables según su valor test, que mide cuántas desviaciones estándar se aleja el promedio del grupo del promedio global.

invisible(capture.output(cd <- catdes(data.frame(cluster = paises$cluster, X), num.var = 1)))

tab_vtest <- bind_rows(lapply(names(cd$quanti), function(gr) {
  m <- as.data.frame(cd$quanti[[gr]])
  tibble(Grupo = gr, var = rownames(m), vtest = m[["v.test"]],
         media_g = m[["Mean in category"]], media_t = m[["Overall mean"]], p = m[["p.value"]])
})) %>%
  mutate(Variable = unname(etiquetas[var])) %>%
  arrange(Grupo, desc(abs(vtest))) %>%
  select(Grupo, Variable, `Promedio del grupo` = media_g, `Promedio global` = media_t,
         `Valor test` = vtest, `Valor p` = p)

tabla_t("Variables que más caracterizan a cada grupo (valor test)",
        dt(tab_vtest, filtro = "top", n = 8, scrollX = TRUE) %>%
          fr(c("Promedio del grupo", "Promedio global", "Valor test"), 2) %>%
          formatSignif("Valor p", 3, dec.mark = ","))
Tabla 16. Variables que más caracterizan a cada grupo (valor test)
Fuente: elaboración propia con base en los WDI, 2019.

Un valor test positivo alto indica que el grupo tiene valores de esa variable muy superiores a los del conjunto, y uno negativo alto, muy inferiores; los valores absolutos mayores que 2 son estadísticamente significativos. Con la caja de filtro bajo el encabezado “Grupo” se puede ver cada grupo por separado. Para el primer grupo las variables más características son las mortalidades y la natalidad (valores test positivos) y la esperanza de vida (negativo); para el tercero, el orden se invierte. Casi todas las variables son significativas en los tres grupos, lo que confirma que la segmentación no descansa en un solo indicador.

Nombre y perfil de cada grupo

dom_reg <- paises %>%
  count(cluster, region) %>%
  group_by(cluster) %>%
  slice_max(n, n = 1, with_ties = FALSE) %>%
  ungroup() %>%
  mutate(p = 100 * n / as.vector(table(paises$cluster)))
dom_ing <- paises %>%
  count(cluster, income) %>%
  group_by(cluster) %>%
  slice_max(n, n = 1, with_ties = FALSE) %>%
  ungroup() %>%
  mutate(p = 100 * n / as.vector(table(paises$cluster)))
i_col <- which(paises$country_code == "COL")
grupo_col <- as.character(paises$cluster[i_col])
col <- paises[i_col, ]
gcol <- as.integer(paises$cluster[i_col])

cent_g <- apply(S, 2, function(v) tapply(v, paises$cluster, mean))
d_g <- sqrt(rowSums((S - cent_g[as.character(paises$cluster), , drop = FALSE])^2))
tipicos_g <- sapply(levels(paises$cluster), function(gr) {
  en <- paises$cluster == gr
  lista_y(paises$country_name[en][order(d_g[en])][1:3])
})
niv <- levels(paises$cluster)
fuera_africa <- paises$country_name[paises$cluster == niv[1] & paises$region != "África Subsahariana"]
ricos_g2 <- paises$country_name[paises$cluster == niv[2] & paises$income == "Alto"]
no_ricos_g3 <- paises$country_name[paises$cluster == niv[3] & paises$income != "Alto"]
n_ing_g2 <- n_distinct(paises$income[paises$cluster == niv[2]])

Los grupos se nombraron según la etapa de la transición demográfica y epidemiológica que describen.

1. Transición temprana (44 países). Son los países con la mortalidad más alta y la transición más rezagada: esperanza de vida de 62,1 años, mortalidad de menores de 5 años de 71 por 1.000 nacidos vivos, fecundidad de 4,4 hijos por mujer y 41,5 % de población menor de 15 años. Las enfermedades transmisibles causan el 50,4 % de las muertes, la desnutrición afecta al 21,2 % de la población y la vacunación DPT llega al 78 %, con un gasto en salud de 4,8 % del PIB. El 86 % pertenece a la región África Subsahariana. Sus países más típicos, los más cercanos al centro del grupo, son Burkina Faso, Camerún y Guinea-Bisáu. Fuera de África Subsahariana solo aparecen Afganistán, Haití, Pakistán, Papúa Nueva Guinea, Timor-Leste y Yibuti.

Vivir en uno de estos países significa que la principal amenaza sigue siendo morir joven por una causa prevenible: 71 de cada 1.000 niños no llegan a cumplir cinco años y la mitad de las muertes se debe a infecciones, problemas del parto o desnutrición. Son, además, las poblaciones más jóvenes del mundo, de modo que la demanda de servicios materno-infantiles y de educación seguirá creciendo durante décadas.

2. Transición intermedia (66 países). Perfil intermedio: esperanza de vida de 73,2 años, mortalidad de menores de 5 años de 20 por 1.000, fecundidad de 2,4 hijos por mujer y 6,3 % de población de 65 años o más. Predominan las enfermedades no transmisibles (75,4 % de las muertes), la desnutrición baja a 7,3 % y el gasto en salud es de 5,5 % del PIB. Su ingreso más frecuente es el medio-alto (52 %). Sus países más típicos son Paraguay, Uzbekistán y Nicaragua.

Es el grupo de la doble carga: todavía conserva una mortalidad de menores de 5 años 4 veces mayor que la del grupo avanzado, pero ya muere sobre todo de enfermedades crónicas. También es el más heterogéneo en ingreso, con 4 niveles distintos. Allí conviven países de ingreso bajo con países de ingreso alto como Arabia Saudí, Emiratos Árabes Unidos, Israel, Kuwait, Mauricio, Omán, Panamá, Seychelles y Trinidad y Tobago; varios de ellos quedan aquí porque sus poblaciones son jóvenes y, en el caso de los países del Golfo, porque la migración laboral les da una tasa bruta de mortalidad muy baja. Es la prueba más clara de que el dinero por sí solo no define la etapa sanitaria de un país.

3. Transición avanzada (52 países). Países con la mayor longevidad y el menor riesgo de muerte: esperanza de vida de 79,6 años, mortalidad de menores de 5 años de 5,2 por 1.000, fecundidad de 1,5 hijos por mujer y 17,7 % de población de 65 años o más. El 89,4 % de las muertes se debe a enfermedades no transmisibles y el gasto en salud alcanza el 8,6 % del PIB. Su tasa bruta de mortalidad (9,9 por 1.000) es mayor que la del grupo intermedio (6,0) pese a su mejor salud, por el envejecimiento. Su ingreso más frecuente es el alto (73 %). Sus países más típicos son Chequia, Reino Unido y Polonia.

Su reto ya no es evitar muertes infantiles sino sostener sistemas de salud para poblaciones envejecidas y con baja fecundidad. Lo interesante es quiénes llegaron aquí sin ser ricos: 14 de sus 52 países no son de ingreso alto, entre ellos Albania, Armenia, Bosnia y Herzegovina, Bulgaria, China, Costa Rica, Cuba y Georgia. Casos como Cuba, Costa Rica o China se citan en la literatura de salud pública como ejemplos de buena salud con ingresos moderados, gracias a una atención primaria extendida.

Por qué tres etapas y no tres tipos de países. Los tres grupos no son países de naturaleza distinta, sino tres momentos de una misma transición: en la temprana la mortalidad apenas empieza a caer, en la intermedia ya cayó pero la población sigue siendo joven, y en la avanzada la población envejece y dominan las enfermedades crónicas. Todos los países recorren el mismo camino, pero no al mismo ritmo, y los determinantes socioeconómicos, empezando por el ingreso, explican solo en parte cuánto ha avanzado cada uno. Esa relación es la que se examina en la validación con el ingreso y la región.

Visualización de los grupos

Las siguientes vistas muestran los grupos desde distintos ángulos: en el plano de los componentes, en tres dimensiones, en el mapa, con sus países más representativos y en la base de datos.

Plano de componentes

plot_ly(coords, x = ~Dim1, y = ~Dim2, color = ~cluster, colors = pal_cl,
        symbol = ~cluster, symbols = c("circle", "square", "diamond", "cross", "x", "triangle-up")[seq_len(k_opt)],
        type = "scatter", mode = "markers", text = ~pais, height = 620,
        marker = list(size = 10, opacity = 0.88, line = list(color = "white", width = 0.8)),
        hovertemplate = "<b>%{text}</b><br>CP1: %{x:.2f}<br>CP2: %{y:.2f}<extra></extra>") %>%
  estilo(eje(1), eje(2), tit_g("Grupos de países en el plano de CP1 y CP2"),
         l = 90, b = 90) %>%
  layout(shapes = lineas_cero, legend = leyenda_h("Grupo"))
Gráfico 22. Grupos de países en el plano de CP1 y CP2
Fuente: WDI, Banco Mundial | 2019

Los grupos se separan sobre todo a lo largo del eje horizontal, el de desarrollo sanitario y demográfico: el primero queda a la izquierda, el intermedio al centro y el avanzado a la derecha. En vertical se distinguen subgrupos por envejecimiento y mortalidad bruta: los países jóvenes de poblaciones con tasa bruta baja se ubican abajo, y los envejecidos arriba. El país atípico en el extremo izquierdo es República Centroafricana. Entre grupos contiguos hay países en la frontera, lo que confirma que se trata de un gradiente y no de bloques aislados.

Vista 3D

Esta vista añade el tercer componente como tercer eje. Es solo exploratoria: el tercer componente explica 4,8 % de la variabilidad y no se usó en el análisis.

plot_ly(coords, x = ~Dim1, y = ~Dim2, z = ~Dim3, color = ~cluster, colors = pal_cl,
        type = "scatter3d", mode = "markers", text = ~pais, height = 660,
        marker = list(size = 4, opacity = 0.88),
        hovertemplate = "<b>%{text}</b><br>CP1: %{x:.2f}<br>CP2: %{y:.2f}<br>CP3: %{z:.2f}<extra></extra>") %>%
  con_tit(tit_g("Grupos de países en los tres primeros componentes")) %>%
  layout(font = fuente_plotly,
         scene = list(xaxis = list(title = "CP1: desarrollo sanitario y demográfico"),
                      yaxis = list(title = "CP2: mortalidad bruta y envejecimiento"),
                      zaxis = list(title = "CP3 (exploratorio)")),
         legend = leyenda_b("Grupo"),
         margin = list(t = 30, b = 60, l = 10, r = 10), paper_bgcolor = "rgba(0,0,0,0)") %>%
  cfg()
Gráfico 23. Grupos de países en los tres primeros componentes
Fuente: WDI, Banco Mundial | 2019

Al girar el gráfico se ve que los grupos se separan en los dos primeros ejes y que el tercero apenas añade separación: los países de los tres grupos se mezclan a lo largo de CP3. Esto respalda la decisión de retener solo dos componentes, porque una tercera dimensión no revela estructura adicional.

Mapa

escala <- do.call(c, lapply(seq_len(k_opt), function(i) {
  list(c((i - 1) / k_opt, pal_cluster[i]), c(i / k_opt, pal_cluster[i]))
}))

plot_ly(paises, type = "choropleth", locations = ~country_code, z = ~as.numeric(cluster),
        text = ~paste0(country_name, " — ", cluster), hoverinfo = "text",
        colorscale = escala, zmin = 0.5, zmax = k_opt + 0.5,
        marker = list(line = list(color = "white", width = 0.4)),
        colorbar = list(title = "Grupo", tickvals = seq_len(k_opt), ticktext = levels(paises$cluster),
                        len = 0.6, thickness = 14),
        height = 580) %>%
  con_tit(tit_g("Mapa de los grupos de países")) %>%
  layout(font = fuente_plotly,
         geo = list(showframe = FALSE, showcoastlines = FALSE, projection = list(type = "natural earth"),
                    showland = TRUE, landcolor = "#e3e6e4",
                    showcountries = TRUE, countrycolor = "#ffffff", countrywidth = 0.4,
                    showocean = FALSE, showlakes = FALSE,
                    bgcolor = "rgba(0,0,0,0)"),
         margin = list(t = 30, b = 10, l = 10, r = 10),
         paper_bgcolor = "rgba(0,0,0,0)") %>%
  cfg()
Gráfico 24. Mapa de los grupos de países
Fuente: WDI, Banco Mundial | 2019

Los países en gris claro no forman parte de la muestra, porque les faltaba información en alguna de las 15 variables. El primer grupo está compuesto en un 86 % por países de África Subsahariana, el segundo en un 32 % por países de América Latina y el Caribe y el tercero en un 75 % por países de Europa y Asia Central. El mapa confirma que los perfiles de salud tienen una geografía, pero también muestra excepciones: países vecinos que quedan en grupos distintos, y países lejanos que comparten grupo.

Países representativos

Para cada grupo se identifican los países más cercanos a su centro, que son los más típicos, y los más alejados, que son los más atípicos.

cent <- apply(S, 2, function(col) tapply(col, paises$cluster, mean))
dist_cent <- sqrt(rowSums((S - cent[as.character(paises$cluster), , drop = FALSE])^2))

rep_df <- paises %>%
  mutate(dist = dist_cent) %>%
  group_by(cluster)

tipicos <- rep_df %>% slice_min(dist, n = 5, with_ties = FALSE) %>% mutate(Tipo = "Más representativo")
atipicos <- rep_df %>% slice_max(dist, n = 3, with_ties = FALSE) %>% mutate(Tipo = "Más atípico")

tab_rep <- bind_rows(tipicos, atipicos) %>%
  ungroup() %>%
  arrange(cluster, desc(Tipo), dist) %>%
  transmute(Grupo = cluster, Tipo, País = country_name, Región = region, Ingreso = income,
            `Distancia al centro` = dist)

tabla_t("Países más representativos y más atípicos de cada grupo",
        dt(tab_rep, filtro = "top", n = 8) %>% fr("Distancia al centro", 2))
Tabla 17. Países más representativos y más atípicos de cada grupo
Fuente: elaboración propia con base en los WDI, 2019.

Los países representativos son los que mejor encarnan el perfil de su grupo y sirven como ejemplo al describirlo; los atípicos están en la frontera con otro grupo o presentan valores extremos. El país más alejado del centro de su grupo en toda la muestra es República Centroafricana, a una distancia de 12,6, en el grupo 1. Transición temprana.

Países por grupo

lista_paises <- paises %>%
  group_by(Grupo = cluster) %>%
  summarise(Países = n(), Listado = paste(sort(country_name), collapse = ", "), .groups = "drop")

tabla_t("Países que integran cada grupo",
        kbl(lista_paises, format = "html", align = c("l", "c", "l"),
            col.names = c("Grupo", "N.º de países", "Países que lo integran")) %>%
          kable_styling(full_width = TRUE) %>%
          column_spec(1, width = "16%", color = "#0b522c") %>%
          column_spec(2, width = "10%") %>%
          column_spec(3, width = "74%"))
Tabla 18. Países que integran cada grupo
Grupo N.º de países Países que lo integran
1. Transición temprana 44 Afganistán, Angola, Benín, Botsuana, Burkina Faso, Camerún, Chad, Comoras, Congo, Côte d’Ivoire, Esuatini, Etiopía, Gabón, Gambia, Ghana, Guinea, Guinea-Bisáu, Haití, Kenia, Liberia, Madagascar, Malaui, Mali, Mauritania, Mozambique, Namibia, Níger, Nigeria, Pakistán, Papúa Nueva Guinea, República Centroafricana, República Democrática del Congo, Ruanda, Senegal, Sierra Leona, Somalia, Sudán, Tanzania, Timor-Leste, Togo, Uganda, Yibuti, Zambia, Zimbabue
2. Transición intermedia 66 Arabia Saudí, Argelia, Argentina, Azerbaiyán, Bangladés, Belice, Bolivia, Brasil, Cabo Verde, Camboya, Colombia, Ecuador, Egipto, El Salvador, Emiratos Árabes Unidos, Filipinas, Fiyi, Guatemala, Guyana, Honduras, India, Indonesia, Irak, Irán, Islas Salomón, Israel, Jamaica, Jordania, Kazajistán, Kirguistán, Kiribati, Kuwait, Laos, Líbano, Libia, Malasia, Marruecos, Mauricio, México, Mongolia, Myanmar (Birmania), Nepal, Nicaragua, Omán, Panamá, Paraguay, Perú, República Dominicana, Samoa, San Vicente y las Granadinas, Santo Tomé y Príncipe, Seychelles, Siria, Sri Lanka, Sudáfrica, Surinam, Tailandia, Tayikistán, Trinidad y Tobago, Túnez, Turkmenistán, Turquía, Uzbekistán, Vanuatu, Venezuela, Vietnam
3. Transición avanzada 52 Albania, Alemania, Armenia, Australia, Austria, Barbados, Bélgica, Bosnia y Herzegovina, Bulgaria, Canadá, Chequia, Chile, China, Chipre, Corea del Sur, Costa Rica, Croacia, Cuba, Dinamarca, Eslovenia, España, Estados Unidos, Estonia, Finlandia, Francia, Georgia, Grecia, Hungría, Irlanda, Islandia, Italia, Japón, Letonia, Lituania, Luxemburgo, Macedonia del Norte, Malta, Moldavia, Montenegro, Noruega, Nueva Zelanda, Países Bajos, Polonia, Portugal, Reino Unido, Rumanía, Rusia, Serbia, Suecia, Suiza, Ucrania, Uruguay
Fuente: elaboración propia con base en los WDI, 2019.

Cada fila es un grupo, con el número de países y su lista completa en orden alfabético. Leerla de corrido es una forma rápida de poner a prueba la segmentación: conviene ver si los países de un mismo grupo son realmente comparables entre sí y si hay compañías que sorprenden, por ejemplo países de ingresos muy distintos en el grupo intermedio.

Base con el grupo asignado

base_cl <- paises %>%
  select(País = country_name, Grupo = cluster, Región = region, Ingreso = income,
         all_of(names(vars))) %>%
  rename_with(~ unname(etiquetas[.x]), all_of(names(vars)))

tabla_t("Base de datos con el grupo asignado a cada país",
        dt(base_cl, filtro = "top", scrollX = TRUE) %>%
          fr(unname(etiquetas[names(vars)]), 2))
Tabla 19. Base de datos con el grupo asignado a cada país
Fuente: elaboración propia con base en los WDI, 2019.

Es la base de datos del modelo con una columna adicional que indica el grupo de cada país. Puede buscarse un país por nombre o filtrarse por grupo, región o ingreso para consultar sus indicadores.

Validación con las variables de apoyo

Los grupos se construyeron sin usar región, ingreso ni la meta ODS. Si aun así coinciden con ellas, la segmentación tiene respaldo externo. Cada pestaña compara los grupos con una de las variables de apoyo.

barra_apilada <- function(var, pal, titulo, leyenda, derecha = FALSE) {
  d <- paises %>%
    count(cluster, across(all_of(var))) %>%
    setNames(c("cluster", "cat", "n")) %>%
    group_by(cluster) %>%
    mutate(pct = 100 * n / sum(n)) %>%
    ungroup()
  plot_ly(d, x = ~cluster, y = ~pct, color = ~cat, colors = pal, type = "bar",
          text = ~paste0(n, " países"), height = 520,
          hovertemplate = "%{x}<br>%{fullData.name}: %{y:.1f} % (%{text})<extra></extra>") %>%
    estilo("Grupo", "Porcentaje de países del grupo", titulo, l = 90, b = 90,
           r = if (derecha) 290 else 30, yextra = list(range = c(0, 100))) %>%
    layout(barmode = "stack", legend = if (derecha) leyenda_v(leyenda) else leyenda_h(leyenda))
}

Nivel de ingreso

barra_apilada("income", pal_ingreso, tit_g("Nivel de ingreso dentro de cada grupo"), "Nivel de ingreso")
Gráfico 25. Nivel de ingreso dentro de cada grupo
Fuente: WDI, Banco Mundial | 2019

Cada barra suma 100 %. Si los grupos coincidieran exactamente con el ingreso, cada barra tendría un solo color. El primer grupo está compuesto principalmente por países de ingreso bajo (48 %) y el tercero por países de ingreso alto (73 %), pero el grupo intermedio mezcla varios niveles. La segmentación guarda una relación clara con el ingreso sin reducirse a él: hay países cuyo perfil de salud es mejor o peor de lo que sugiere su ingreso.

El 95 % de los países de ingreso bajo está en el primer grupo y el 81 % de los de ingreso alto en el tercero: el ingreso acierta en los extremos, pero deja de ser una guía confiable en la zona media, donde el perfil de salud depende de otros factores. Para quien diseña política esto importa, porque clasificar a un país solo por su ingreso lo ubica bien en los extremos y puede equivocarse justo en el centro, donde hay más margen de mejora.

Región

barra_apilada("region", pal_region, tit_g("Región dentro de cada grupo"), "Región", derecha = TRUE)
Gráfico 26. Región dentro de cada grupo
Fuente: WDI, Banco Mundial | 2019

Cada barra suma 100 %. Un grupo dominado por un solo color indica un perfil de salud compartido por una región, y uno con muchos colores reúne países geográficamente dispersos con perfiles parecidos. El primer grupo está dominado por África Subsahariana (86 %), el segundo por América Latina y el Caribe (32 %) y el tercero por Europa y Asia Central (75 %). La geografía importa, pero ningún grupo coincide por completo con una región.

Meta ODS

barra_apilada("Meta_ODS", pal_meta, tit_g("Cumplimiento de la meta ODS 3.2 dentro de cada grupo"), "Meta ODS 3.2")
Gráfico 27. Cumplimiento de la meta ODS 3.2 dentro de cada grupo
Fuente: WDI, Banco Mundial | 2019

Este cruce traduce los grupos al lenguaje de la política pública. En el primer grupo ningún país cumple la meta de 25 muertes por 1.000 nacidos vivos; en el intermedio lo hace el 79 % y en el avanzado el 100 %. Esta variable se construye con una de las 15 del modelo, así que no es una validación independiente, pero muestra qué grupos están más lejos del objetivo.

La distancia a la meta se puede dimensionar: para que el primer grupo llegue a 25 por 1.000, su mortalidad de menores de 5 años tendría que bajar en promedio de 71 a 25, es decir, cerca de 65 %, en el plazo que fija la Agenda 2030.

Tabla de ingreso

gi <- as.data.frame.matrix(table(paises$cluster, paises$income)) %>%
  rownames_to_column("Grupo")

tabla_t("Número de países por grupo y nivel de ingreso", dt(gi, n = 5, dom = "t", scrollX = TRUE))
Tabla 20. Número de países por grupo y nivel de ingreso
Fuente: elaboración propia con base en los WDI, 2019.

Las filas son los grupos y las columnas los niveles de ingreso. Los valores concentrados en la diagonal indican correspondencia entre la segmentación y el ingreso, y los valores fuera de ella señalan países cuyo perfil de salud difiere del esperado por su ingreso, que son los casos más interesantes para el análisis de políticas.

Estabilidad de los grupos

Un buen agrupamiento no debería cambiar por completo al modificar una decisión razonable del análisis. Para comprobarlo, la clusterización se repitió en seis escenarios y cada resultado se comparó con la solución principal mediante el índice de Rand ajustado, que vale 1 cuando las dos agrupaciones coinciden por completo y cerca de 0 cuando solo coinciden por azar. El índice no depende de cómo se numeren los grupos.

rand_aj <- function(a, b) {
  t <- table(a, b)
  s_ij <- sum(choose(t, 2))
  s_a <- sum(choose(rowSums(t), 2))
  s_b <- sum(choose(colSums(t), 2))
  esp <- s_a * s_b / choose(sum(t), 2)
  (s_ij - esp) / ((s_a + s_b) / 2 - esp)
}

ward_k <- function(M, kk = k_opt) cutree(hclust(dist(M), method = "ward.D2"), kk)

ward_acp <- function(Xs, q = NULL) {
  p <- PCA(Xs, scale.unit = TRUE, ncp = ncol(Xs), graph = FALSE)
  if (is.null(q)) q <- max(2, sum(p$eig[, 1] > 1))
  ward_k(p$ind$coord[, 1:q, drop = FALSE])
}

base_cl <- as.integer(paises$cluster)
cent_e <- apply(S, 2, function(v) tapply(v, paises$cluster, mean))
atipico <- which.max(sqrt(rowSums((S - cent_e[as.character(paises$cluster), , drop = FALSE])^2)))

set.seed(2019)
g_km <- kmeans(S, centers = k_opt, nstart = 50)$cluster

esc <- tibble(
  Escenario = c("Tres componentes en lugar de dos",
                "Ward sobre las 15 variables estandarizadas, sin ACP",
                "Sin la tasa bruta de mortalidad",
                "Sin la desnutrición (variable truncada en 2,5 %)",
                paste0("Sin el país más alejado del centro de su grupo (", paises$country_name[atipico], ")"),
                "K-medias en lugar de Ward"),
  ari = c(rand_aj(base_cl, ward_k(pca$ind$coord[, 1:3])),
          rand_aj(base_cl, g_std),
          rand_aj(base_cl, ward_acp(X[, setdiff(names(X), "Tasa_Mortalidad")])),
          rand_aj(base_cl, ward_acp(X[, setdiff(names(X), "Desnutricion")])),
          rand_aj(base_cl[-atipico], ward_acp(X[-atipico, ], q = ncp)),
          rand_aj(base_cl, g_km))
) %>%
  arrange(ari) %>%
  mutate(Escenario = factor(Escenario, levels = Escenario),
         color = case_when(ari >= 0.75 ~ "#0b522c", ari >= 0.5 ~ "#52b788", TRUE ~ "#c7a64a"))

plot_ly(esc, x = ~ari, y = ~Escenario, type = "bar", orientation = "h", height = 440,
        marker = list(color = ~color), text = ~f2(ari), textposition = "outside", cliponaxis = FALSE,
        hovertemplate = "%{y}<br>Rand ajustado: %{x:.2f}<extra></extra>") %>%
  estilo("Índice de Rand ajustado frente a la solución principal", "",
         tit_g("Coincidencia de los grupos al cambiar decisiones del análisis"),
         l = 330, b = 90, xextra = list(range = c(0, 1.12))) %>%
  layout(shapes = list(list(type = "line", x0 = 0.75, x1 = 0.75, y0 = 0, y1 = 1, yref = "paper",
                            line = list(color = "#c7a64a", dash = "dash", width = 2))))
Gráfico 28. Coincidencia de los grupos al cambiar decisiones del análisis
Fuente: WDI, Banco Mundial | 2019

Las barras verde oscuro superan 0,75, el valor a partir del cual la coincidencia se considera alta. ¿Qué significa, por ejemplo, un índice de 0,96? Que si se toman dos países cualesquiera, las dos agrupaciones casi siempre toman la misma decisión sobre ellos (dejarlos juntos o separarlos), una vez descontadas las coincidencias que se darían por puro azar. Un índice de 0 significaría que el cambio produce grupos tan distintos como si los países se hubieran repartido al azar.

5 de los 6 escenarios superan 0,75. Que k-medias, un algoritmo que agrupa con otra lógica, llegue a una partición casi igual (0,96) indica que los grupos no son un artefacto del método de Ward, y que retirar al país más alejado del centro de su grupo apenas cambie el resultado indica que ningún caso extremo está arrastrando la segmentación.

El escenario que más mueve los grupos es el que quita la tasa bruta de mortalidad (0,40). Esto no es una señal de inestabilidad, sino algo esperable: esa variable construye casi por sí sola el segundo componente. Al quitarla, el segundo eje deja de medir el envejecimiento con mortalidad bruta alta y pasa a medir otra cosa, y con él cambian las fronteras entre grupos, en especial la de los grupos intermedio y avanzado, que ese eje ayuda a separar. El resultado confirma, en otras palabras, que el segundo componente aporta información real a la segmentación y no es ruido.

Regiones y grupos de ingreso proyectados

La descarga de DataBank también trae los agregados del Banco Mundial: el mundo, las regiones y los grupos de ingreso. No se usaron para construir los componentes ni los grupos, porque repetirían información de los países. Pero sí se pueden proyectar sobre los ejes ya calculados, como individuos suplementarios, y asignar cada uno al grupo cuyo centro le queda más cerca. Así se ve en qué etapa de la transición está, en promedio, cada región.

nom_agr <- c(WLD = "Mundo", LCN = "América Latina y el Caribe", SSF = "África Subsahariana",
             EAS = "Asia Oriental y Pacífico", ECS = "Europa y Asia Central",
             MEA = "Oriente Medio, Norte de África, Afganistán y Pakistán", NAC = "Norteamérica",
             SAS = "Asia Meridional", LIC = "Ingreso bajo", LMC = "Ingreso medio-bajo",
             UMC = "Ingreso medio-alto", HIC = "Ingreso alto")
corto_agr <- c(WLD = "Mundo", LCN = "Am. Latina", SSF = "África Subs.", EAS = "Asia Or.",
               ECS = "Europa y A. C.", MEA = "O. Medio y N. Áfr.", NAC = "Norteamérica",
               SAS = "Asia Merid.", LIC = "Ing. bajo", LMC = "Ing. medio-bajo",
               UMC = "Ing. medio-alto", HIC = "Ing. alto")

agr <- ancho %>%
  filter(country_code %in% names(nom_agr)) %>%
  drop_na(all_of(names(vars)))

Xa <- agr %>% select(all_of(names(vars))) %>% as.data.frame()
rownames(Xa) <- agr$country_code
coord_a <- sweep(predict(pca, Xa)$coord[, 1:ncp, drop = FALSE], 2, signos, "*")

cent_S <- apply(S, 2, function(v) tapply(v, paises$cluster, mean))
grupo_a <- apply(coord_a, 1, function(z) rownames(cent_S)[which.min(colSums((t(cent_S) - z)^2))])

d_a <- tibble(cod = rownames(coord_a), Dim1 = coord_a[, 1], Dim2 = coord_a[, 2], grupo = grupo_a) %>%
  mutate(nombre = unname(nom_agr[cod]), corto = unname(corto_agr[cod]),
         tipo = factor(case_when(cod == "WLD" ~ "Mundo",
                                 cod %in% c("LIC", "LMC", "UMC", "HIC") ~ "Grupo de ingreso",
                                 TRUE ~ "Región"),
                       levels = c("Grupo de ingreso", "Mundo", "Región")))

pal_tipo <- c("Grupo de ingreso" = "#7b6d8d", "Mundo" = "#8c5a2b", "Región" = "#a23b5e")
simb_tipo <- c("Grupo de ingreso" = "square", "Mundo" = "star", "Región" = "diamond")

cx <- mean(d_a$Dim1)
cy <- mean(d_a$Dim2)
d_a <- d_a %>%
  mutate(ang = atan2(Dim2 - cy, Dim1 - cx)) %>%
  arrange(ang) %>%
  mutate(radio = rep(c(45, 85), length.out = n()),
         ax = radio * cos(ang), ay = -radio * sin(ang))

etiquetas_agr <- lapply(seq_len(nrow(d_a)), function(i) {
  list(x = d_a$Dim1[i], y = d_a$Dim2[i], text = d_a$corto[i], showarrow = TRUE,
       ax = d_a$ax[i], ay = d_a$ay[i], arrowcolor = "#9aa89f", arrowwidth = 0.8, arrowhead = 0,
       font = list(size = 12, color = "#1c1c1c"), bgcolor = "rgba(255,255,255,0.8)", borderpad = 2)
})

cent_df <- tibble(Dim1 = cent_S[, 1], Dim2 = cent_S[, 2], grupo = rownames(cent_S))

p_agr <- plot_ly(height = 740) %>%
  add_markers(data = coords, x = ~Dim1, y = ~Dim2, color = ~cluster, colors = pal_cl, text = ~pais,
              marker = list(size = 7, opacity = 0.55),
              hovertemplate = "%{text}<extra></extra>")

p_agr <- p_agr %>%
  add_markers(data = cent_df, x = ~Dim1, y = ~Dim2, name = "Centro de cada grupo", inherit = FALSE,
              text = ~grupo, hovertemplate = "Centro del grupo<br>%{text}<extra></extra>",
              marker = list(size = 24, symbol = "circle-open", color = unname(pal_cl[cent_df$grupo]),
                            line = list(color = unname(pal_cl[cent_df$grupo]), width = 3)))

for (tp in levels(d_a$tipo)) {
  di <- filter(d_a, tipo == tp)
  p_agr <- p_agr %>%
    add_markers(data = di, x = ~Dim1, y = ~Dim2, name = tp, inherit = FALSE,
                text = ~paste0("<b>", nombre, "</b><br>Grupo más cercano: ", grupo),
                hovertemplate = "%{text}<extra></extra>",
                marker = list(size = 14, symbol = simb_tipo[[tp]], color = pal_tipo[[tp]],
                              line = list(color = "white", width = 1.5)))
}

p_agr <- p_agr %>%
  estilo(eje(1), eje(2), tit_g("Regiones y grupos de ingreso proyectados sobre el plano de los países"),
         l = 90, b = 90, r = 270,
         xextra = list(range = c(-9.5, 6.5)),
         yextra = list(range = c(-3.6, 3.6))) %>%
  layout(shapes = lineas_cero, annotations = etiquetas_agr, legend = leyenda_v("Leyenda"))

p_agr
Gráfico 29. Regiones y grupos de ingreso proyectados sobre el plano de los países
Fuente: WDI, Banco Mundial | 2019
tabla_t("Grupo más cercano a cada agregado del Banco Mundial",
        kbl(d_a %>% arrange(Dim1) %>%
              transmute(Agregado = nombre, Tipo = tipo, CP1 = f2(Dim1), CP2 = f2(Dim2), `Grupo más cercano` = grupo),
            format = "html", align = c("l", "l", "c", "c", "l")) %>%
          kable_styling(full_width = TRUE))
Tabla 21. Grupo más cercano a cada agregado del Banco Mundial
Agregado Tipo CP1 CP2 Grupo más cercano
África Subsahariana Región -4,96 0,20 1. Transición temprana
Ingreso bajo Grupo de ingreso -4,69 -0,20 1. Transición temprana
Ingreso medio-bajo Grupo de ingreso -1,56 -0,51 2. Transición intermedia
Oriente Medio, Norte de África, Afganistán y Pakistán Región -0,92 -1,04 2. Transición intermedia
Asia Meridional Región -0,29 -0,80 2. Transición intermedia
Mundo Mundo 0,43 0,47 2. Transición intermedia
América Latina y el Caribe Región 1,10 -0,14 2. Transición intermedia
Ingreso medio-alto Grupo de ingreso 1,79 -0,39 2. Transición intermedia
Asia Oriental y Pacífico Región 2,21 -0,09 3. Transición avanzada
Europa y Asia Central Región 2,89 1,10 3. Transición avanzada
Norteamérica Región 3,31 1,56 3. Transición avanzada
Ingreso alto Grupo de ingreso 3,41 1,30 3. Transición avanzada
Fuente: elaboración propia con base en los WDI, 2019.

El encuadre del gráfico deja fuera a República Centroafricana, cuyos valores extremos en ambos ejes alargarían los ejes y apretarían al resto de los países; se puede ver ampliando hacia afuera con los controles de la esquina. Para leer las coordenadas, el cero de cada eje corresponde al país promedio de la muestra, y un valor negativo en el primer eje indica una transición menos avanzada que la de ese país promedio. El mundo queda en 0,43 en el primer eje: la persona promedio del planeta vive en condiciones de salud y demografía algo más avanzadas que las del país promedio, porque los promedios del Banco Mundial pesan más a los países más poblados.

El mundo en su conjunto queda en el grupo 2. Transición intermedia. Por regiones, Oriente Medio, Norte de África, Afganistán y Pakistán (Transición intermedia); Asia Meridional (Transición intermedia); América Latina y el Caribe (Transición intermedia); Asia Oriental y Pacífico (Transición avanzada); Europa y Asia Central (Transición avanzada); Norteamérica (Transición avanzada); África Subsahariana (Transición temprana). Los grupos de ingreso se ordenan sobre el primer eje de izquierda a derecha, lo que confirma desde otro ángulo la relación entre ingreso y transición.

Hay que leer estos puntos con cuidado: los agregados del Banco Mundial son promedios ponderados por población, así que describen a la persona promedio de cada región y no al país promedio. Por eso una región puede caer en un grupo distinto del de la mayoría de sus países, como ocurre cuando un país muy poblado (India en Asia Meridional o China en Asia Oriental) arrastra el promedio.

Colombia frente a su grupo

Colombia es el caso de interés para este trabajo. Esta sección la ubica con más detalle: con qué países comparte perfil y en qué indicadores se aparta del país típico de su grupo.

Colombia se ubica en el grupo 2. Transición intermedia. Para ponerlo en concreto: Colombia tiene una esperanza de vida de 76,8 años, por encima del promedio de su grupo (73,2), una mortalidad de menores de 5 años de 13,5 por 1.000 (promedio del grupo: 19,9) y una fecundidad de 1,71 hijos por mujer (promedio del grupo: 2,40). Ya cumple la meta ODS 3.2. Su tasa de mortalidad de menores de 5 años está por debajo del umbral de 25 por 1.000, de modo que su reto en salud infantil es sostener lo logrado y reducir las diferencias internas.

d_col <- as.matrix(dist(S))[i_col, ]
vec_col <- order(d_col)[2:9]

tabla_t("Los ocho países más parecidos a Colombia en el plano de los componentes",
        kbl(tibble(País = paises$country_name[vec_col],
                   Distancia = f2(d_col[vec_col]),
                   Grupo = as.character(paises$cluster[vec_col]),
                   Región = paises$region[vec_col],
                   `Nivel de ingreso` = as.character(paises$income[vec_col])),
            format = "html", align = c("l", "c", "l", "l", "l")) %>%
          kable_styling(full_width = TRUE))
Tabla 22. Los ocho países más parecidos a Colombia en el plano de los componentes
País Distancia Grupo Región Nivel de ingreso
Túnez 0,22 2. Transición intermedia Oriente Medio y Norte de África Medio-bajo
Líbano 0,24 2. Transición intermedia Oriente Medio y Norte de África Medio-alto
Sri Lanka 0,28 2. Transición intermedia Asia Meridional Medio-alto
Panamá 0,42 2. Transición intermedia América Latina y el Caribe Alto
Tailandia 0,49 2. Transición intermedia Asia Oriental y Pacífico Medio-alto
Irán 0,60 2. Transición intermedia Oriente Medio y Norte de África Medio-alto
Costa Rica 0,66 3. Transición avanzada América Latina y el Caribe Medio-alto
Turquía 0,72 2. Transición intermedia Europa y Asia Central Medio-alto
Fuente: elaboración propia con base en los WDI, 2019.
Zc <- scale(X)
perf_col <- tibble(var = orden_var,
                   Colombia = Zc[i_col, orden_var],
                   Grupo = colMeans(Zc[paises$cluster == grupo_col, orden_var, drop = FALSE])) %>%
  mutate(dif = Colombia - Grupo,
         Variable = factor(unname(etq_corta[var]), levels = rev(unname(etq_corta[orden_var]))))

plot_ly(perf_col, y = ~Variable, x = ~Grupo, type = "bar", orientation = "h", height = 620,
        name = paste("Promedio del grupo", grupo_col), marker = list(color = "#b7dcc6"),
        hovertemplate = "%{y}<br>Promedio del grupo: %{x:.2f} desv. est.<extra></extra>") %>%
  add_bars(x = ~Colombia, name = "Colombia", marker = list(color = "#0b522c"),
           hovertemplate = "%{y}<br>Colombia: %{x:.2f} desv. est.<extra></extra>") %>%
  estilo("Distancia al promedio de todos los países (desviaciones estándar)", "",
         tit_g("Colombia frente al promedio de su grupo en los 15 indicadores"),
         l = 170, b = 90, xextra = list(zeroline = TRUE, zerolinecolor = "#1b4332")) %>%
  layout(barmode = "group", bargap = 0.25, legend = leyenda_h(""))
Gráfico 30. Colombia frente al promedio de su grupo en los 15 indicadores
Fuente: WDI, Banco Mundial | 2019
mas_arriba <- perf_col %>% arrange(desc(dif)) %>% slice(1:2)
mas_abajo <- perf_col %>% arrange(dif) %>% slice(1:2)

Los países con un perfil más cercano al de Colombia son Túnez, Líbano, Sri Lanka, Panamá, Tailandia. Solo 2 de los ocho son de su misma región: Colombia se parece más a países en una etapa similar de la transición que a sus vecinos geográficos.

En el gráfico, cada par de barras compara a Colombia con el país típico de su grupo, ambos medidos frente al promedio mundial. Como referencia para leer el gráfico, una desviación estándar equivale a 8,1 años de esperanza de vida, a 33,4 muertes de menores de 5 años por cada 1.000 nacidos vivos o a 1,32 hijos por mujer. Donde Colombia más se aleja hacia arriba de su grupo es en gasto corriente en salud y esperanza de vida al nacer, y hacia abajo en población de 0 a 14 años y tasa de fecundidad. Son los rasgos que la distinguen dentro de su etapa y, por tanto, los puntos en los que la comparación con sus pares es más útil para la política pública.

Lo que el modelo no ve, pero los datos sí. Las 15 variables dejan fuera una causa de muerte que en Colombia pesa mucho: las lesiones (homicidios, accidentes de tránsito y suicidios). Como las muertes transmisibles y no transmisibles suman 85,7 %, el 14,3 % restante corresponde a lesiones, frente a una mediana de 8,0 % en el mundo y de 9,6 % en su grupo. Colombia ocupa el puesto 12 de 162 en este indicador, junto a países como Siria, Afganistán, El Salvador y Honduras. Esto también explica por qué la mortalidad adulta masculina colombiana es 1,9 veces la femenina: buena parte de esa diferencia son hombres jóvenes que mueren por causas violentas.

En síntesis, Colombia está en la etapa intermedia con indicadores de longevidad, mortalidad infantil y fecundidad que ya la acercan al grupo avanzado, y sus pares más cercanos (Túnez, Líbano, Sri Lanka y Panamá) son países que comparten esa misma etapa en otros continentes. Sus retos son tres: el envejecimiento acelerado que anuncia una fecundidad de 1,71 hijos por mujer, por debajo del nivel de reemplazo; la carga de enfermedades crónicas, que ya causan 76 de cada 100 muertes; y una mortalidad por lesiones muy alta, asociada a la violencia y a los accidentes de tránsito. Los promedios nacionales, además, esconden las brechas entre regiones del país, que los registros vitales del DANE permiten seguir con más detalle (DANE, 2020).

Interpretación de resultados

sil_global <- mean(sil_df$s)
p_bajo_g1 <- 100 * mean(paises$cluster[paises$income == "Bajo"] == niv[1])
p_alto_g3 <- 100 * mean(paises$cluster[paises$income == "Alto"] == niv[3])
meta_g <- sapply(niv, function(gr) 100 * mean(paises$Meta_ODS[paises$cluster == gr] == "Cumple"))
ari_km <- esc$ari[esc$Escenario == "K-medias en lugar de Ward"]
reg_av <- d_a$nombre[d_a$tipo == "Región" & d_a$grupo == niv[3]]
reg_tem <- d_a$nombre[d_a$tipo == "Región" & d_a$grupo == niv[1]]

¿Qué componentes principales explican mayor variabilidad y qué representan? El primer componente explica el 70,6 % de la variabilidad y representa el desarrollo sanitario y demográfico: ordena a los países desde los de alta mortalidad, natalidad y carga de enfermedades transmisibles hasta los de alta longevidad y predominio de enfermedades crónicas. Con un valor propio de 10,59, resume tanta información como 11 de los 15 indicadores juntos. El segundo explica el 12,0 % y representa la mortalidad bruta y el envejecimiento, un fenómeno distinto, ligado a la estructura por edades. Juntos explican el 82,5 %.

¿Cuántos clusters se formaron y qué características definen cada grupo? Se formaron 3 grupos: 1. Transición temprana (44 países, esperanza de vida de 62,1 años, fecundidad de 4,4 hijos y la mitad de las muertes por causas transmisibles), 2. Transición intermedia (66 países, 73,2 años, 2,4 hijos y doble carga de enfermedad) y 3. Transición avanzada (52 países, 79,6 años, 1,5 hijos y población envejecida). Saber a qué grupo pertenece un país explica el 77,4 % de lo que lo diferencia de los demás en el plano de los componentes.

¿Se observan patrones interesantes entre los países? Sí, y tres de ellos no eran evidentes antes del análisis. El primero es que los grupos siguen al ingreso en los extremos pero no en el centro: hay países de ingreso alto en el grupo intermedio (Arabia Saudí, Emiratos Árabes Unidos, Israel y Kuwait) y países de ingreso medio en el avanzado (Albania, Armenia, Bosnia y Herzegovina y Bulgaria). El segundo es que la tasa bruta de mortalidad, el indicador más intuitivo, es el que peor describe la salud: es mayor en el grupo avanzado que en el intermedio, porque mide la edad de la población y no el riesgo de morir. El tercero es geográfico: Colombia se parece más a Túnez, Líbano y Sri Lanka que a la mayoría de sus vecinos, porque lo que agrupa a los países es la etapa de la transición, no la cercanía.

El hallazgo de fondo es que la salud de los países no se ordena en categorías separadas sino a lo largo de un gradiente continuo, y que los grupos son una forma útil de simplificarlo. De ahí se desprenden dos consecuencias para la política: como hay un eje dominante, las acciones que mejoran un indicador tienden a mover los demás; y como el ingreso explica solo en parte la posición de un país, existe margen para que las decisiones de política y la cobertura de servicios básicos adelanten la transición.

Conclusiones

La pregunta que guio el trabajo era si los indicadores de mortalidad, salud y estructura demográfica permiten identificar grupos de países con perfiles similares. La respuesta es afirmativa, con un matiz importante: los grupos existen y son estables, pero no son compartimentos estancos, sino tres etapas de una misma transición que los países recorren a velocidades distintas. Los hallazgos que sostienen esa respuesta son siete.

  1. La salud y la demografía de un país son un solo proceso. Un único componente resume el 70,6 % de la información de los 15 indicadores. Mortalidad infantil, fecundidad, esperanza de vida, causas de muerte y estructura por edades no son problemas separados sino manifestaciones de la misma transición. Para la política pública esto significa que las intervenciones se refuerzan entre sí: cuando cae la mortalidad infantil, con los años cae también la fecundidad, la población envejece y cambian las enfermedades que hay que atender.

  2. La tasa bruta de mortalidad engaña. El segundo componente (12,0 %) está construido casi solo por ella y refleja la edad de la población, no su salud. Bulgaria tiene una tasa bruta 17 veces mayor que Emiratos Árabes Unidos y, sin embargo, ambos países viven más de 75 años en promedio. Comparar la salud de dos países con este indicador lleva a conclusiones equivocadas; la esperanza de vida o las tasas ajustadas por edad son la medida correcta.

  3. Los países forman tres etapas de un continuo, no bloques aislados. La silueta media de 0,52 indica grupos bien definidos pero con fronteras graduales, y 2 países quedan justo en el límite entre dos etapas. Aun así, la segmentación es robusta: se mantiene en 5 de los 6 escenarios de estabilidad, y un algoritmo distinto, k-medias, llega a casi la misma partición (Rand ajustado de 0,96).

  4. Las brechas entre etapas son enormes. Un niño que nace en un país de transición temprana tiene 14 veces más probabilidad de morir antes de los cinco años que uno de transición avanzada, y vive 18 años menos. Ningún país del primer grupo cumple la meta ODS 3.2; para alcanzarla, su mortalidad de menores de 5 años tendría que caer en promedio un 65 %.

  5. El ingreso acierta en los extremos y se equivoca en el medio. El 95 % de los países de ingreso bajo está en la transición temprana y el 81 % de los de ingreso alto en la avanzada, pero el grupo intermedio mezcla 4 niveles de ingreso. Países como Cuba, Costa Rica o China alcanzaron la etapa avanzada sin ser ricos, y varios países del Golfo siguen en la intermedia pese a su riqueza. Clasificar a un país solo por su ingreso es, por tanto, una mala guía para decidir qué necesita en salud.

  6. La persona promedio del mundo vive en la etapa intermedia. Proyectados sobre el mismo plano, el mundo queda en el grupo 2. Transición intermedia; Asia Oriental y Pacífico, Europa y Asia Central y Norteamérica quedan en la etapa avanzada, y África Subsahariana en la temprana. La geografía de la transición es clara: el gran rezago está concentrado en un solo subcontinente.

  7. Colombia está en la etapa intermedia, cerca de la avanzada, con un rasgo propio. Su esperanza de vida (76,8 años), su mortalidad de menores de 5 años (13,5 por 1.000) y su fecundidad (1,71) son mejores que el promedio de su grupo, pero las lesiones causan el 14,3 % de sus muertes, una de las proporciones más altas de la muestra. Su agenda ya no es la de un país pobre: es prepararse para un envejecimiento rápido, atender la carga creciente de enfermedades crónicas y reducir la mortalidad violenta.

Contraste de las hipótesis. Las tres hipótesis planteadas en la introducción se sostienen con los resultados:

Hipótesis Resultado Evidencia principal
H1. Un primer componente ordena a los países según la transición Se confirma CP1 explica el 70,6 % y correlaciona con 12 de las 15 variables por encima de 0,7
H2. Los grupos son cortes de un gradiente continuo Se confirma Silueta media de 0,52, países en la frontera y polígonos del radar ordenados sin cruzarse
H3. Los grupos se parecen al ingreso sin coincidir con él Se confirma 95 % de los países de ingreso bajo en el grupo 1 y 81 % de los de ingreso alto en el grupo 3, pero 4 niveles de ingreso en el grupo intermedio

Limitaciones. Es un corte de un solo año, por lo que describe dónde está cada país pero no a qué velocidad avanza; seis de las quince variables pertenecen al bloque de mortalidad, lo que refuerza el peso del primer componente; el ACP supone relaciones lineales; Ward es sensible al número de grupos y a los países atípicos, como República Centroafricana, cuyos valores extremos pueden provenir de estimaciones modeladas en contextos de crisis; la desnutrición está truncada en 2,5 %; las lesiones, una causa de muerte decisiva para países como Colombia, quedaron fuera del modelo; y se excluyeron 54 economías con datos faltantes, en su mayoría territorios y microestados.

Trabajo futuro. El paso natural es repetir el análisis para varios años, por ejemplo de 2000 a 2019, y medir la velocidad con que cada país se mueve sobre el primer componente: así se sabría no solo en qué etapa está, sino cuánto le falta para pasar a la siguiente. También valdría la pena incluir las lesiones como cuarta causa de muerte y aplicar el mismo método a los departamentos de Colombia, donde las brechas internas probablemente son tan grandes como las que separan a los grupos de países.

Usos en economía y políticas públicas

Una tipología de este tipo sirve para lo mismo que una segmentación de mercado en la empresa: dejar de tratar a todos igual y diseñar una respuesta para cada grupo.

  • 1. Transición temprana: la prioridad es la supervivencia infantil. Las intervenciones de mayor rendimiento son baratas y conocidas: vacunación completa, atención calificada del parto, agua potable, mosquiteros, suplementos nutricionales y tratamiento de la neumonía y la diarrea. Es el grupo donde cada peso de cooperación internacional salva más vidas, y donde la meta ODS 3.2 está más lejos: ninguno de sus países la cumple.
  • 2. Transición intermedia: la prioridad es manejar la doble carga. Hay que consolidar lo logrado en salud infantil, donde todavía el 21 % de los países no cumple la meta, y al mismo tiempo montar la detección temprana de hipertensión, diabetes y cáncer antes de que el envejecimiento dispare sus costos. Es también el momento de aprovechar el bono demográfico: ahorrar e invertir mientras hay muchas personas en edad de trabajar.
  • 3. Transición avanzada: la prioridad es la sostenibilidad. Con 17,7 % de población mayor de 65 años y 1,5 hijos por mujer, el reto es financiar pensiones, cuidados de largo plazo y tratamientos crónicos con cada vez menos población en edad de trabajar, y hacerlo con eficiencia: el caso de Estados Unidos muestra que gastar más no garantiza mejores resultados.

Además, los grupos permiten definir conjuntos de comparación (benchmarking) entre países con perfiles semejantes. Para Colombia, compararse con Túnez, Líbano y Sri Lanka es más útil que compararse con el promedio de América Latina o con los países de la OCDE, porque comparten la misma etapa y, por tanto, problemas parecidos. Los grupos sirven también para asignar recursos de cooperación según necesidades y no solo según ingreso, y para seguir el avance de las metas de desarrollo sostenible relacionadas con salud: un país que cambia de grupo entre dos años es un país que avanzó de etapa.

Anexo: reproducibilidad

El documento se genera completo con Knit desde una sesión limpia de R, siempre que la carpeta del proyecto contenga tres archivos: MetadataWDB.csv o DataWDB.csv, la descarga de DataBank con los indicadores de 2019 (el primero trae además la ficha oficial de cada indicador), y estiloverde.css, la hoja de estilo del informe. Al compilar, el propio documento crea base_final_mortalidad_2019.csv, con una fila por país y todas las variables del análisis, de modo que cualquier persona que lo ejecute obtiene exactamente la misma base y los mismos resultados.

Bibliografía